How to distinguish between reference and value in golang - go

package main
type A struct {
Num int
}
func getA() A {
return A{Num: 10}
}
func main() {
if getA().Num == 10 {
// getA().Num = 20 // why not working
myA := getA()
myA.Num = 20
}
}
why "getA().Num = 20" line do not working?
I'm don't know the difference between
myA := getA()
myA.Num = 20
and
//getA().Num = 20 // why not working
I think it just two line and one line...
I'm more familiar with Java.
What I need to know to understand it?
I expected the code working correctly....

Tweak your function declaration like this, and it will work as you're expecting:
func getA() *A {
return &A{Num: 10}
}
What has changed is that getA returns a pointer to a value of type A.
In Java, class data types are always used as references (like a pointer), except the language doesn't use an explicit notation like this. So, writing Go code to use pointer types like *A is similar to what you're used to in Java.
The part that may confuse you is that Java doesn't have a direct equivalent for Go's non-pointer types, like the plain A in your Go code. In Java, you can only declare a class type, which always acts as a reference.

Related

Finding the type of a variable through static analysis? [duplicate]

This question already has an answer here:
Golang static identifier resolution
(1 answer)
Closed 4 months ago.
How can I determine the type of a variable through static analysis?
Suppose I have the following code:
func doSomething(x interface{}) {}
func main() {
p := Person()
doSomething(p)
}
And I want to analyze doSomething(person), is it possible to get the type of Person through static analysis?
What if there were multiple levels of assignment?
p1 := Person()
p2 := p1
doSomething(p2)
or
parent := Parent()
p := Parent.Child() // type Person
doSomething(p)
The use case is that I have a generic function that is commonly used throughout the (very large) codebase, and would like to introduce a new type safe version of this function. To do this, I hope to automatically determine the "type" of the function and refactor it accordingly:
// old
DB.InsertRow(person)
// new
Person.InsertRow(person)
Finding the type of an expression through static analysis is non-trivial, and sometimes not possible, for details see Golang static identifier resolution.
The use case is that I have a generic function that is commonly used throughout the (very large) codebase, and would like to introduce a new type safe version of this function. To do this, I hope to automatically determine the "type" of the function and refactor it accordingly:
// old
DB.InsertRow(person)
// new
Person.InsertRow(person)
Just for refactoring purposes, I don't think it is worth the hassle to implement it.
What you may do is change the signature of DB.InsertRow() temporarily to accept only a specific type such as int or your custom type you're sure is not used anywhere (e.g. type tempFoo struct{}).
To what end? Doing so, the compiler will do the hard work for you. You will see error messages showing exactly the types your codebase is trying to pass to DB.InsertRow(), so I'd say mission accomplished.
For example this code compiles:
func doSomething(x interface{}) {}
func main() {
doSomething(image.Pt(1, 2))
doSomething("abc")
doSomething(image.Rect) // image.Rect is a function which we don't call,
// so we're passing a value of a function type here
}
If we change doSomething():
func doSomething(x int) {}
We get the types we're seeking for from the compiler:
./prog.go:10:14: cannot use image.Pt(1, 2) (value of type image.Point) as type int in argument to doSomething
./prog.go:11:14: cannot use "abc" (untyped string constant) as int value in argument to doSomething
./prog.go:12:14: cannot use image.Rect (value of type func(x0 int, y0 int, x1 int, y1 int) image.Rectangle) as type int in argument to doSomething
Using the advice from Golang static identifier resolution to use golang.org/x/tools/go/types, I found that this was pretty straight forward to do with the golang.org/x/tools/go/analysis package, which has the types info available alongside the parsed ast.
This was my solution:
package rewriter
import (
"go/ast"
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"
"golang.org/x/tools/go/ast/inspector"
)
func run(pass *analysis.Pass) (interface{}, error) {
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
nodeFilter := []ast.Node{
(*ast.CallExpr)(nil),
}
inspect.Nodes(nodeFilter, func(node ast.Node, push bool) bool {
callExpr, ok := node.(*ast.CallExpr)
if !ok {
return true
}
funcExpr, ok := callExpr.Fun.(*ast.SelectorExpr)
if !ok {
return true
}
// check method name
if funcExpr.Sel.Name != "doSomething" {
return true
}
for _, arg := range callExpr.Args {
// lookup type of the arg
argType := pass.TypesInfo.Types[arg].Type
if argType.String() == "*rewriter.Person" {
// do whatever you want here
}
}
return false
})
return nil, nil
}
One can augment this to look at the receiver of the method and add refactoring logic as needed (using analysis.Diagnostic).

golang function type inheritance?

Consider this example in Go language:
type I interface {
get() string
}
type S struct {}
func (s *S) get() string {
return "here!"
}
var sSupplier = func() *S {
return &S{}
}
func foo(supplier func () I) {
i := supplier()
println(i)
}
func main() {
foo(sSupplier) // compile error, type mismatch
}
Type S inherit interface I. But apparently type func () *S does not inherit func () I, so I cannot call foo with sSupplier in place of the supplier function. Is there a way to fix it without forcing sSupplier to return type I?
In java you can use generics to do something like <T extends I> void foo(Supplier<T> supplier) {...} then call foo(sSupplier); with Supplier<S> sSupplier type. I'm not sure if similar approach is possible in go?
If you think for a bit about what generics do for you, they are really a way to ask the compiler to compile, on the spot, an anonymous wrapper function or lambda or whatever is needed to map from some concrete type. That is, given something like (I'll use C++ syntax here rather than Java as I'm much more familiar with C++):
template<T>
void f(T obj) {
// do stuff with the object
}
you're telling the compiler that when it sees f(int_value) it should build a function f that takes an int, and when it sees f(struct S) it should build a function f that takes a struct S, and so on. (This is a bit more natural in Java than it is in C++'s C underpinnings since Java does the whole argument-matching thing to decide which of these various f functions to call.)
In effect, instead of writing the actual function, you write a template—hence the C++ keyword—that the compiler can use to, at compile time, produce the function you really wanted. Since Go lacks generics, it lacks this sort of template-expansion trick.
That leaves you with several obvious alternatives, though. One is exemplified by go:generate (see, e.g., Explain go generate in this example). In this particularly simple case, though, you can just write the expansion yourself in line:
foo(func() I { return sSupplier() })
See a more complete example on the Go playground. I replacd your println(i) with fmt.Printf("%#v\n", i) to print the interface object's value in a slightly more useful form.

Confusing for these pieces of code of interface implementation and calling?

Version of Go
go version go1.11 darwin/amd64
Code 1:
package main
import "fmt"
type myintf interface {
GotU()
}
type esc struct {
i int
}
//func GotU(t esc);
func (e esc)GotU() {
e.i = 10
}
func TestFunc(it myintf) string {
it.GotU()
return "kk"
}
func main() {
var test esc
test.i = 9
TestFunc(test)
fmt.Println(test.i)
}
Code 2:
package main
import "fmt"
type myintf interface {
GotU()
}
type esc struct {
i int
}
func (e esc)GotU() {
e.i = 10
}
func TestFunc(it myintf) string {
it.GotU()
return "kk"
}
func main() {
var test esc
test.i = 9
TestFunc(&test)
fmt.Println(test.i)
}
Code 3:
package main
import "fmt"
type myintf interface {
GotU()
}
type esc struct {
i int
}
func (e *esc)GotU() {
e.i = 10
}
func TestFunc(it myintf) string {
it.GotU()
return "kk"
}
func main() {
var test esc
test.i = 9
TestFunc(test)
fmt.Println(test.i)
}
The outputs:
code 1 output: 9
code 2 output: 9
code 3 cannot be compiled due to a type mismatch
Since only func (e esc)GotU() implemented, why should both pieces of code work and deliver the same result?
It's kind of confusing for me to pass a pointer of struct to that function (TestFunc) to get the same answer.
The last code snippet has implemented a method receiver of pointer type. This will consider the situation if you want to modify the value of receiver.
func (e *esc) GotU() {
e.i = 10
}
In above case Since you are passing pointer type receiver on a method which is implementing the interface.
type myintf interface {
GotU()
}
So you need to pass address of struct in TestFunc. This is the reason you are getting type mismatch error, because you are passing variable of esc type while your method requires variable of *esc.
func main() {
var test esc
test.i = 9
TestFunc(&test)
fmt.Println(test.i)
}
Working example on Go playground
In Golang there are two ways to pass a method receiver.
func (s *MyStruct) pointerMethod() { } // method on pointer
func (s MyStruct) valueMethod() { } // method on value
For programmers unaccustomed to pointers, the distinction between
these two examples can be confusing, but the situation is actually
very simple. When defining a method on a type, the receiver (s in the
above examples) behaves exactly as if it were an argument to the
method. Whether to define the receiver as a value or as a pointer is
the same question, then, as whether a function argument should be a
value or a pointer. There are several considerations
First, and most important, does the method need to modify the receiver? If it does, the receiver must be a pointer. (Slices and maps act as references, so their story is a little more subtle, but for instance to change the length of a slice in a method the receiver must still be a pointer.) In the examples above, if pointerMethod modifies the fields of s, the caller will see those changes, but valueMethod is called with a copy of the caller's argument (that's the definition of passing a value), so changes it makes will be invisible to the caller.
The difference between the 1st and second version is, that you pass the struct directly in one version and the pointer to the struct in the other version. In this case these programs work the same, as the pointer also includes the all defined funcs on the struct.
But this does not work the other way around. You define the method GotU on the pointer receiver. The struct does not know about this func. If you would call
TestFunc(&test)
in the third program, it would compile but work differently than the other two: The output is: "10"
As the GotU is defined on the pointer receiver test is passed as reference and the modifications persist. In the other programs test is passed as value, i.e. it is copied, the copy is modified in GotU. When the func exits, the copy is discarded and the old version is still the same as before.

Is there a constructor interface for a struct type?

In golang, say I have a type that needs some setup done on it before use beyond just setting default values. ex:
type dice struct {
input string
count int
sides int
result int
}
func (d *dice) Roll() {
//initialize random seed
rand.Seed(time.Now().UnixNano())
for i := 0; i < d.count; i++ {
d.result = d.result + rand.Intn(d.sides)+1)
}
}
Simple example but say if I wanted to have d.Roll() called automatically when creating an instance of the 'dice' type is there a way to do that? More in line with the issue I'm trying to solve, say I wanted the rand.Seed(time.Now().UnixNano()) bits to be called automatically before I call Roll() is there an idiomatic golang way to do this?
Basically "How do you handle constructor functionality in golang?" is my question. Is there an interface for this I can add?
No, Go doesn't provide this kind of interface. You just can't use a constructor like you would do in C++ by example.
The current idiom is to create a function
NewX(args...) X // or *X
in which you can setup your struct as you want. In your case, it could look like this:
func NewDice() dice {
var d dice
d.Roll()
return d
}
There is not. But the common, and I would say idiomatic, thing to do is to put a func NewDice() dice in your package and then you can just call it to get an instance. Do your set up there. It serves the same purpose as a constructor. It's pretty common to have package level methods like NewMyType that do initilization and return and instance.

In golang, how do I re-assign an external reference from within a function?

I'm probably not expressing this correctly in the question, but perhaps this code will make it clearer:
package main
import "fmt"
type Blob struct {
Message string
}
func assign1(bb **Blob) {
*bb = &Blob{"Internally created by assign1"}
}
func (b *Blob) assign2() {
*b = Blob{"Internally created by assign2"}
}
func main() {
x1 := &Blob{"Hello World"}
assign1(&x1)
fmt.Printf("x1 = %+v\n", *x1)
x2 := Blob{"Hello World"}
x2.assign2()
fmt.Printf("x2 = %+v\n", x2)
}
Produces, as desired:
x1 = {Message:Internally created by assign1}
x2 = {Message:Internally created by assign2}
I want to pass a reference (pointer to a pointer) into a function and have the function assign a new value to the pointer such that the calling scope will see that new value.
I've figured out the above two ways of doing this, but I'd like to know if they are actually correct or if there is some hidden flaw. Also, are either of them more idiomatic than the other?
Coming from Java, assign2 just seems wrong but I'm sure I've seen something similar in the encoding/json package. What is that actually doing?
Thanks!
James answers the mechanics of assign2. I'll touch a bit on when to use it.
Let's take a simpler example, first.
type Counter uint
func (c *Counter) Increment() {
*c += 1
}
In the counter example the entire state of the receiver is changing. Similarly for the encoding/json package the entire state of the receiver is changing. That's really the only time I would use that style.
One major advantage of the style: you can define an interface for the change, just like the GobDecoder does.
When I first saw the assign2 style it was a little grating. But then I remembered that (c *Counter) Increment gets translated to Increment(c *Counter) in the machine code and it didn't bother me anymore. I personally prefer assign1-style. (Though, there is no need for the double pointers as orignally posted.)
package main
import "fmt"
type Blob struct {
Message string
}
func assign1(b *Blob) {
*b = Blob{"Internally created by assign1"}
}
func main() {
x1 := Blob{"Hello World"}
assign1(&x1)
fmt.Printf("x1 = %+v\n", *x1)
}
Both forms are valid Go, as you've discovered.
For the assign2 case, the compiler finds that assign2 does not appear in Blob's method set, but it is part of *Blob's method set. It then converts the method call to:
(&x2).assign2()
While it can be confusing if a method then goes and changes x2 like in your example, there are a number of places in the standard library where this pattern is used. Probably the most common one is implementing custom decoding for a type with the encoding/json module: you implement the DecodeJSON method with a pointer receiver, and update the value being pointed to.

Resources