Printf function show struct differently - go

I am using compile function of regex package which returns pointer of Regexp struct and passing struct in printf function shows me only string not whole struct.
package main
import (
"fmt"
"regexp"
)
func main() {
reg, _ := regexp.Compile(`[0-9a-f]+`)
fmt.Printf("%+v \n", reg)
}
// Output
[0-9a-f]+
But when I created my own struct and initialising with some value and print it then it shows full struct. I am not understanding the concept here.
package main
import (
"fmt"
)
type Exp struct {
a string
b int
}
func main() {
x := &Exp{"akash", 12}
fmt.Printf("%+v \n", x)
}
// Output: &{akash 12}

The regexp.Regexp type implements the fmt.Stringer interface, which is the default verb used in the fmt.Print* methods.
This means that it calls reg.String() when formatting in your first example.
In your second example, your custom type Exp, has no such method, so it uses default Go-formatting of the struct.

Related

How to get a pointer of an interface

It's hard to explain, but how I can get a pointer of a something that implements some interface?
Consider the code below:
package main
import (
"fmt"
"unsafe"
)
type Interface interface {
Example()
}
type StructThatImplementsInterface struct {
}
func (i *StructThatImplementsInterface) Example() {
}
type StructThatHasInterface struct {
i Interface
}
func main() {
sameInterface := &StructThatImplementsInterface{}
struct1 := StructThatHasInterface{i: sameInterface}
struct2 := StructThatHasInterface{i: sameInterface}
TheProblemIsHere(&struct1)
TheProblemIsHere(&struct2)
}
func TheProblemIsHere(s *StructThatHasInterface) {
fmt.Printf("Pointer by Printf: %p \n", s.i)
fmt.Printf("Pointer by Usafe: %v \n", unsafe.Pointer(&s.i))
}
https://play.golang.org/p/HoC5_BBeswA
The result will be:
Pointer by Printf: 0x40c138
Pointer by Usafe: 0x40c140
Pointer by Printf: 0x40c138
Pointer by Usafe: 0x40c148
Notice that the Printf gets the same value (because both StructThatHasInterface uses the same sameInterface). However, the unsafe.Pointer() returns distinct values.
How can I get the same result of Printf without use fmt, and reflect if possible?
In the current version of Go, an interface value is two words long. The concrete value or a pointer to the concrete value is stored in the second word. Use the following code to get the second word as a uintptr:
u := (*[2]uintptr)(unsafe.Pointer(&s.i))[1]
This code is unsafe and is not guaranteed to work in future.
The supported way to get the pointer is:
u := reflect.ValueOf(s.i).Pointer()

Convert data to base64 encode in go

I am new to go programming language and I'm stock on this scenario on my code.
Here's my example code:
a := genreAPI{Genre{"Pop"}, Genre{"Rock"}}
fmt.Println("Value of a :", a)
The current output is: Value of a : [{Pop} {Rock}]
How can I achieved an output like this:
Value of a : [{UG9w} {Um9jaw==}]
which is a base64 encode?
I am not sure what exactly is not clear from the documentation. Not only it has a clear name which explains states what the method is doing, it also has an example.
package main
import (
"encoding/base64"
"fmt"
)
func main() {
data := []byte("Pop")
str := base64.StdEncoding.EncodeToString(data)
fmt.Println(str) // UG9w
}
Go Playground
You can customise the output of print functions by providing a String() method for your type. Either for the whole Genre or just for the name variable.
Example:
package main
import (
"encoding/base64"
"fmt"
)
type Base64String string
func (b Base64String) String() string {
return base64.StdEncoding.EncodeToString([]byte(b))
}
type Genre struct {
Name Base64String
}
func main() {
a := []Genre{Genre{"Pop"}, Genre{"Rock"}}
fmt.Println(a) // prints [{UG9w} {Um9jaw==}]
fmt.Println(string(a[0].Name)) // prints Pop
}

Name of a struct to a string

How do I print the name of the type of a struct, i.e. so I can include it in a print statement, i.e. something like
type MyStruct struct { ... }
func main() {
fmt.Println(MyStruct.className())
}
If this is possible, would it be considered a slow operation? (i.e. reflection)
For example,
package main
import "fmt"
type MyStruct struct{}
func main() {
fmt.Printf("%T\n", MyStruct{})
}
Output:
main.MyStruct
The fmt %T print verb gives a Go-syntax representation of the type of the value.
The Go fmt package uses the reflect package for run-time reflection.

What's the difference between new(Struct) and &Struct{} in Go?

They seem to be the same:
package main
import "fmt"
type S struct {
i int
}
func main() {
var s1 *S = new(S)
fmt.Println(s1)
var s2 *S = &S{}
fmt.Println(s2) // Prints the same thing.
}
Update:
Hm. I just realized that there's no obvious way to initialize S.i using new. Is there a way to do that? new(S{i:1}) does not seem to work :/
From Effective Go:
As a limiting case, if a composite literal contains no fields at all, it creates a zero value for the type. The expressions new(File) and &File{} are equivalent.
Not only do they give the same resulting value, but if we allocate something both ways and look at their values...
// Adapted from http://tour.golang.org/#30
package main
import "fmt"
type Vertex struct {
X, Y int
}
func main() {
v := &Vertex{}
v2 := new(Vertex)
fmt.Printf("%p %p", v, v2)
}
...we'll see that they are in fact allocated in consecutive memory slots. Typical output: 0x10328100 0x10328108. I'm not sure if this is an implementation detail or part of the specification, but it does demonstrate that they're both being allocated from the same pool.
Play around with the code here.
As for initializing with new, according to the language spec: The built-in function new takes a type T and returns a value of type *T. The memory [pointed to] is initialized as described in the section on initial values. Because functions in go can't be overloaded, and this isn't a variadic function, there's no way to pass in any initialization data. Instead, go will initialize it with whatever version of 0 makes sense for the type and any member fields, as appropriate.
Case 1: package main
import (
"fmt"
)
type Drink struct {
Name string
Flavour string
}
func main() {
a := new(Drink)
a.Name = "Maaza"
a.Flavour = "Mango"
b := a
fmt.Println(&a)
fmt.Println(&b)
b.Name = "Frooti"
fmt.Println(a.Name)
}//This will output Frooti for a.Name, even though the addresses for a and b are different.
Case 2:
package main
import (
"fmt"
)
type Drink struct {
Name string
Flavour string
}
func main() {
a := Drink{
Name: "Maaza",
Flavour: "Mango",
}
b := a
fmt.Println(&a)
fmt.Println(&b)
b.Name = "Froti"
fmt.Println(a.Name)
}//This will output Maaza for a.Name. To get Frooti in this case assign b:=&a.

golang: can i share C.int between packages

in the main package i have:
var foo C.int
foo = 3
t := fastergo.Ctuner_new()
fastergo.Ctuner_register_parameter(t, &foo, 0, 100, 1)
in the fastergo package i have:
func Ctuner_register_parameter(tuner unsafe.Pointer, parameter *C.int, from C.int, to C.int, step C.int) C.int {
...
}
if i try to run it, i get:
demo.go:14[/tmp/go-build742221968/command-line-arguments/_obj/demo.cgo1.go:21]: cannot use &foo (type *_Ctype_int) as type *fastergo._Ctype_int in function argument
i am not really sure what go is trying to tell me here, but somehow i think it wants to tell me, that all C.int are not equal? why is this the case? how can i solve this / work around?
Since _Ctype_int doesn't begin with a Unicode upper case letter, the type is local to the package. Use Go types, except in the C wrapper package where you convert them to C types. The wrapper package should hide all the implementation details.
You don't provide sufficient information for us to create sample code which compiles and runs. Here's a rough outline of what I expected to see:
package main
import "tuner"
func main() {
var foo int
foo = 3
t := tuner.New()
t.RegisterParameter(&foo, 0, 100, 1)
}
.
package tuner
import (
"unsafe"
)
/*
#include "ctuner.h"
*/
import "C"
type Tuner struct {
ctuner uintptr
}
func New() *Tuner {
var t Tuner
t.ctuner = uintptr(unsafe.Pointer(C.ctuner_new()))
return &t
}
func (t *Tuner) RegisterParameter(parameter *int, from, to, step int) error {
var rv C.int
rv = C.ctuner_register_parameter(
(*C.ctuner)(unsafe.Pointer(t.ctuner)),
(*C.int)(unsafe.Pointer(parameter)),
C.int(from),
C.int(to),
C.int(step),
)
if rv != 0 {
// handle error
}
return nil
}
As explained by peterSO, you can't pass C.int between packages. However, you can pass pointers between packages by converting the pointer type. To do this, you would define a named type in the target package, import that type into the calling package and covert via unsafe.Pointer. There isn't any point in doing this with a single int.
However, it is helpful if you keep code to convert complex types in a package; for example an array of strings (or any sort of nested array).
The example below is for exporting a go function to be called in C, but this works in reverse, ie. if you want to call a C functions which a returns nested array.
package convert
import "C"
type PP_char **C.char
func From_c_to_go(arr_str PP_char, length int) []string {
// Some operation on the Ctype
var slice []string
for _, s := range unsafe.Slice(arr_str, length) {
if s == nil {
break
}
x := C.GoString(s)
slice = append(slice, x)
}
return slice
}
package main
import "C"
import "convert"
//export myFunc
func myFunc(arr_str **C.char, length int){
retyped_arr_str := convert.PP_char(unsafe.Pointer(arr_str))
slice := convert.From_c_to_go(retyped_arr_str, length)
// Do something with slice
}
You could instead decide to pass instance of unsafe.Pointer as an argument to the go function in the target package and perform the type conversion in that function.

Resources