Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I have a map string that looks like this
map[first:[hello] second:[world]]
The problem is that when I iterate over it and return the values they return [hello] [world] and I want them to just return hello world
// currentMap is of type map[interface{}]interface{} originally
newStringMap := make(map[string]interface{})
for k, v := range currentMap {
newStringMap[k.(string)] = v
}
return newStringMap
How can this be done?
From the below information provided by you:
when I iterate over it and return the values they return [hello] [world]
It seems that your currentMap actually stores string slices []string as values, behind the interface{} type. Assuming that above line means that you see this when printing the map using fmt.Println(), or similar functions.
map[first:[hello] second:[world]]
Here's a possible reproduction & solution of your problem::
package main
import (
"fmt"
)
func main() {
currentMap := make(map[interface{}]interface{})
currentMap["first"] = []string{"hello"}
currentMap["second"] = []string{"world"}
newStringMap := make(map[string]interface{})
fmt.Println("Problem:")
fmt.Printf("%v\n", currentMap)
fmt.Println("\nSolution:")
for k, v := range currentMap {
lst, ok := v.([]string)
//fmt.Println(lst, ok)
if ok && len(lst) > 0 {
newStringMap[k.(string)] = v.([]string)[0]
} else {
newStringMap[k.(string)] = nil
}
}
fmt.Printf("%v\n", newStringMap)
}
Which outputs to:
Problem:
map[first:[hello] second:[world]]
Solution:
map[first:hello second:world]
Try it here
https://play.golang.org/p/5XAA3m6MDX_b
It's not necessary that the content stored in currentMap is always of similar type. (if it is, then why would interface{} ever be used). Which means, don't forget your error-checking. I have tried to cover the same. You may need to add some more, based on the possible actual types in the map, similar to this section:
if ok && len(lst) > 0 {
newStringMap[k.(string)] = v.([]string)[0]
} else {
newStringMap[k.(string)] = nil
}
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 days ago.
Improve this question
What would be the most elegant way to check if every item in a slice meets some condition? In my specific scenario, I have a slice of bytes: [16]byte. I need to check if all bytes are 0.
In JS, for example, I would do something like that:
const uint8Array = new Uint8Array([0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0])//Can be thought of as an array of "bytes"
const isEmpty = uint8Array.every(byte=>byte === 0)//Check that every "byte" is zero
console.log(isEmpty)//false
What's the cleanest and most straightforward way to do this in Go?
For readability and flexibility (e.g. if you need to operate on types other than byte), you may benefit from writing a small All generic function that
accepts a slice and a predicate on the element type of that slice, and
returns true if and only if the predicate is satisfied for all elements of the slice.
You'll then be free to put that generic function to use with different slices and predicates.
package main
import "fmt"
func main() {
bs := []byte{15: 1} // slice of 16 bytes, all but the last one of which are zero
isZero := func(b byte) bool { return b == 0 }
fmt.Println(All(bs, isZero)) // false
}
func All[T any](ts []T, pred func(T) bool) bool {
for _, t := range ts {
if !pred(t) {
return false
}
}
return true
}
(Playground)
No need to create a library for that All function, though; a little copying is better than a little dependency.
It would be easy if you use the bytes package, here is an example :
func main() {
n := []byte{0,0,0,0,0,0,0}
b := bytes.ContainsRune(n, 1)
fmt.Println(b)
}
In bytes package there are multiple methods you can call for your result, like checking char, or multiple contains etc.
The most straightforward way is to use a range-based for loop, since as far as I'm aware, Go doesn't have built-in function similar to .ForEach.
If you don't need an index, you can omit it from the loop and you will have something similar:
isEmpty := true
for _, val := range uint8Array {
if val != 0 {
isEmpty=false
break
}
}
fmt.Println(isEmpty)
If you use the function repeatedly, you can define it as your own separate function as well.
func IsEmpty(arr *[]any) bool {
for _, val := range *arr {
if val != 0 {
return false
}
}
return true
}
Although the last one might cause issues for some data types.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I have a struct like this:
type structData struct {
dataName string
dataNum int
}
And I have created a slice out of them, like so:
dataSlice := []*structData{}
I have a loop that populates the dataName string and just after this, I want the struct slice to be checked through and duplicates removed.
I mention this specifically because currently, dataNum is 0. So, I don't want to check if the string inside my struct is same or not, it is totally fine checking if the entire struct is equal (if that's possible, else it is also OKAY for me to check duplicates in the dataName string, I just don't know what would look better in design).
An example output of what my struct slice looks like:
&{dataname1 0}
&{dataname1 0}
&{dataname2 0}
&{dataname2 0}
What I want it to look like:
&{dataname1 0}
&{dataname2 0}
You can use a map to check for duplicates, where your struct is the key to the map.
package main
import (
"fmt"
)
type structData struct {
dataName string
dataNum int
}
func (d *structData) String() string {
return fmt.Sprintf("(%s,%d)", d.dataName, d.dataNum)
}
func main() {
dataSlice := []*structData{
{"dataname1", 0},
{"dataname1", 0},
{"dataname2", 0},
{"dataname2", 0},
}
m := map[structData]struct{}{}
dataSlice2 := []*structData{}
for _, d := range dataSlice {
if _, ok := m[*d]; !ok {
dataSlice2 = append(dataSlice2, d)
m[*d] = struct{}{}
}
}
fmt.Printf("%v\n", dataSlice)
fmt.Printf("%v\n", dataSlice2)
}
https://play.golang.org/p/wL-SfBCMGQj
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I am trying to parse a json-like string which looks like this.
"abc:9, bar:3"
What I would like to have at the end is a map[string]int which looks like this:
map[string]int{"abc":9, "bar":3}
I have gotten as far as splitting it into a set of 'pairs', like so:
`["abc:9", "bar:3"]
I am struggling with how to get that structure into the final map[string]int. I have tried ranging over the slice, but I am missing how to actually get it into the map.
val := "abc:9, bar:3"
lsd := make(map[string]int)
c := strings.Split(val, ",")
for k, v := range c {
lsd = v[k] // where I am struggling, I know this is wrong, but I can't seem to find the proper syntax and tools for this
}
Can anyone point me in the right direction to end up with the map[string]int I am looking for here?
This is a tiny bit cheesy but I was having trouble making fmt.Sscanf grok the pattern, so I am just splitting again. And you may have been missing strconv - strconv.Atoi is a quick converter.
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
lsd := make(map[string]int)
toParse := "abc:5, foo:5"
parts := strings.Split(toParse, ", ")
for _, p := range parts {
results := strings.SplitN(p, ":", 2)
val, err := strconv.Atoi(results[1])
if err != nil {
panic(err) //probably want to do somethig better
}
lsd[results[0]] = val
}
fmt.Printf("%#v", lsd)
}
map[string]int{"abc":5, "foo":5}
https://play.golang.org/p/UadibEzTXWU
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I'm working on a code to deserialize streams of bytes into objects and I'm stuck on getting the pointer of the field of a struct.
Basically how the code works is as follows: it gets the pointer to a struct, then depending on the type it serializes it, ex. if it's an integer it takes the next 4 bytes. The tricky case is if it's a struct because I have to recursively run Deserialize on all of its attributes and I don't know how to get the address of its field to pass them to Deserialize.
func Deserialize(objPtr interface{}, b []byte) (bytesRead int) {
// it should be the address of the object
val := reflect.ValueOf(objPtr).Elem()
valPtr := reflect.ValueOf(objPtr)
// check if either the object or *object is Serializable
_, isSerializable := (val.Interface()).(Serializable)
_, bo := (valPtr.Interface()).(Serializable)
isSerializable = isSerializable || bo
// specific type serialization
if isSerializable{
return objPtr.(Serializable).Deserializebyte(b)
}
switch val.Kind() {
case reflect.Uint32, reflect.Int, reflect.Int32:
res := reflect.ValueOf(binary.LittleEndian.Uint32(b[:4]))
valPtr.Set(res)
return 4
case reflect.Uint64, reflect.Int64:
res := reflect.ValueOf(binary.LittleEndian.Uint32(b[:8]))
valPtr.Set(res)
return 8
case reflect.Struct:
n_bytes := 0
for i := 0; i < val.NumField(); i++ {
// stuck in here
valPtr.Elem()
// I don't think the next line works
last_n_bytes := Deserialize(&(valPtr.Elem().Field(i).Interface()), b)
n_bytes += last_n_bytes
b = b[last_n_bytes:]
}
//valPtr.Set(res)
return n_bytes
default:
panic("this panic is for debug, every case should be handled above")
res := val.Bytes()
valPtr.Set(res)
return len(val.Bytes())
}
return 0
}
Use the reflect API to get the address of the field:
last_n_bytes := Deserialize(valPtr.Elem().Field(i).Addr().Interface(), b)
The superint example panics because the application takes the address of an unexported field through the reflect API. That's not allowed because it would allow another package to modify the field.
Here's a working example with exported fields:
type superint struct {
A int
B int
}
func (s *superint) lol() {}
type a interface{ lol() }
func main() {
i := superint{A: 1, B: 9}
valPtr := reflect.ValueOf(&i)
fmt.Printf("%v \n", &i.A)
fmt.Printf("%v \n", valPtr.Elem().Field(0).Addr().Interface())
}
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
I have the following code and ask my self is this the "go way" to solve the following requirement.
I need to print a directory tree sorted by file age.
package main
import (
"fmt"
"github.com/kr/fs"
"os"
"time"
"sort"
)
type fileinfo struct {
Path string
age time.Duration
}
func main() {
fmt.Print("test range of fs")
walker := fs.Walk("../")
var files []fileinfo
for walker.Step() {
if err := walker.Err(); err != nil {
fmt.Fprintln(os.Stderr, err)
continue
}
age := time.Now().Sub(walker.Stat().ModTime())
files = append(files,fileinfo{walker.Path(),age})
}
sort.Slice(files, func(i, j int) bool {
return files[i].age < files[j].age
})
for i:=0; i < len(files) ; i++ {
fmt.Print("File path: ",files[i].Path," age: ",files[i].age,"\n")
}
}
What's your opinion to the code?
Thanks for help
for i:=0; i < len(files) ; i++ {
fmt.Print("File path: ",files[i].Path," age: ",files[i].age,"\n")
}
for loops over arrays are better written using range iterator. This makes the code easier to read, avoids silly mistakes, and it works with other structures like maps and channels.
for _,file := range files {
fmt.Print("File path: ",file.Path," age: ",file.age,"\n")
}
See Go by Example: Range for more.
Since you have a newline at the end and a space between each element, fmt.Println might work out better than fmt.Print. It automatically puts spaces between each element and a newline at the end.
fmt.Println("File path:", file.Path, "age:", file.age)