I am using syscall to read a byte array out of mmap:
file, e := os.Open(path)
if e != nil {...}
defer file.Close()
fi, e := file.Stat()
if e != nil {...}
data, e := syscall.Mmap(int(file.Fd()), 0, int(fi.Size()), syscall.PROT_READ, syscall.MAP_SHARED)
if e != nil {...}
data is the binary array I need.
I am using || as a delimiter, so I can get slices by using bytes.Split:
slices := bytes.Split(data, []byte("||"))
for _, s := range slices {
str := string(s[:])
fmt.Println(str)
}
This works fine, and I also stored the total number of messages (its type is uint32 which takes 8 bytes) at the beginning of the mmap.
When a new message is written in, I can get the total number of messages by reading the first 8 bytes.
Assuming I have the number of messages as n, I still need to do the following to read the new message:
slices := bytes.Split(data, []byte("||"))
s := slices[n - 1]
str := string(s[:])
fmt.Println(str)
Is there a more efficient way to do this?
I have a string stored as a:
a := `M\u00fcnchen`
fmt.Println(a) // prints "M\u00fcnchen"
b := "M\u00fcnchen"
fmt.Println(b) // prints "München"
Is there a way I can convert a into b ?
You can use strconv.Unquote for this:
u := `M\u00fcnchen`
s, err := strconv.Unquote(`"` + u + `"`)
if err != nil {
// ..
}
fmt.Printf("%v\n", s)
Outputs:
München
I am receiving unknown json from client and I parse to interface like
var f interface{}
err := json.Unmarshal(b, &f)
How to make all keys in f to be lower keys ?
I have to save this f to mongo and I need to make some queries but I want to avoid mistake if somebody send uppercase same json.
Here's one way to do it:
var v any
err := json.Unmarshal(b, &v)
v = lower(v)
where lower is:
func lower(v any) any {
switch v := v.(type) {
case []any:
lv := make([]any, len(v))
for i := range v {
lv[i] = lower(v[i])
}
return lv
case map[string]any:
lv := make(map[string]any, len(v))
for mk, mv := range v {
lv[strings.ToLower(mk)] = mv
}
return lv
default:
return v
}
}
The lower function calls itself recursively to handle key conversion in nested JSON objects and arrays.
playground
If you know that you are working with an object without nesting (the object fields do not contain arrays or other objects), then you can inline the map case from the lower function above:
var v map[string]any
err := json.Unmarshal(b, &v)
lv := make(map[string]any, len(v))
for mk, mv := range v {
lv[strings.ToLower(mk)] = mv
}
v = lv
It will be map[string]interface{} so go over it and simply convert keys to lowercase.
var f map[string]interface{}
...
converted := make(map[string]interface{}, len(f))
for k, v := range f {
converted[strings.ToLower(k)] = v
}
I was reading this doc and saw the following fragment:
The := syntax is shorthand for declaring and initializing a variable, e.g. for var f string = "short" in this case.
f := "short"
fmt.Println(f)
The point is: is it only for strings? Or is it dymanic enough to understand what datatype should it store?
And plus: isn't it the same of var f = "short"?
Of course it infers the obvious type(s) returned by the expression on the right side.
The specification gives those examples :
i, j := 0, 10
f := func() int { return 7 }
ch := make(chan int)
r, w := os.Pipe(fd) // os.Pipe() returns two values
_, y, _ := coord(p) // coord() returns three values; only interested in y coordinate
Note that it's not dynamic : everything happens at compile time, the type(s) being given by the right part expression.
I have a line containing 3 numbers that I want to read from stdin with fmt.Scanln() but this code won't work:
X := make([]int, 3)
fmt.Scanln(X...)
fmt.Printf("%v\n", X)
I get this error message:
cannot use X (type []int) as type []interface {} in function argument
I don't get it.
Idiomatic Go would be:
func read(n int) ([]int, error) {
in := make([]int, n)
for i := range in {
_, err := fmt.Scan(&in[i])
if err != nil {
return in[:i], err
}
}
return in, nil
}
interface{} means nothing. Please don't use it if you don't have to.
For example,
package main
import "fmt"
func intScanln(n int) ([]int, error) {
x := make([]int, n)
y := make([]interface{}, len(x))
for i := range x {
y[i] = &x[i]
}
n, err := fmt.Scanln(y...)
x = x[:n]
return x, err
}
func main() {
x, err := intScanln(3)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%v\n", x)
}
Input:
1 2 3
Output:
[1 2 3]
I think the the correct version should be
X := make([]int, 3)
fmt.Scanln(&X[0], &X[1], &X[2])
fmt.Printf("%v\n", X)
This error message occurs b/c there's no reasonable way to convert []int to []interface{}. Note, this is in reference to a slice. So the syntax your using is correct, but fmt.Scanln expects []interface{}. This has implications outside of pkg fmt.
The reason I've seen given for this is due to Go giving you control over memory layout so it currently has no reasonable way to do the slice conversion. This means you'll need to do the conversion manually before passing it to a function expecting the slice of a given type. For example:
package main
import (
"fmt"
)
func main() {
x := make([]int, 3)
y := make([]interface{}, 3)
y[0] = x[0]
y[1] = x[1]
y[2] = x[2]
fmt.Println(y...)
}
Or something a little more general:
x := make([]int, 3)
y := make([]interface{}, len(x))
for i, v := range x {
y[i] = v
}
fmt.Println(y...)
Regarding your specific issue, see the following:
x := make([]*int, 3)
for i := range x {
x[i] = new(int)
}
y := make([]interface{}, 3)
for i, v := range x {
y[i] = v
}
if _, err := fmt.Scanln(y...); err != nil {
fmt.Println("Scanln err: ", err)
}
for _, v := range y {
val := v.(*int)
fmt.Println(*val)
}
I saw in a comment you said the lines can have different lengths. In that case
you can implement your own fmt.Scanner:
package main
import (
"bytes"
"fmt"
)
type slice struct {
tok []int
}
func (s *slice) Scan(state fmt.ScanState, verb rune) error {
tok, err := state.Token(false, func(r rune) bool { return r != '\n' })
if err != nil { return err }
if _, _, err := state.ReadRune(); err != nil {
if len(tok) == 0 {
panic(err)
}
}
b := bytes.NewReader(tok)
for {
var d int
_, err := fmt.Fscan(b, &d)
if err != nil { break }
s.tok = append(s.tok, d)
}
return nil
}
func main() {
var s slice
fmt.Scan(&s)
fmt.Println(s.tok)
}
https://golang.org/pkg/fmt#Scanner