update to global variable's member not reflecting in global variable - go

First of all, I am new to Go, so I guess it is obvious to me there is some proper way of doing what I am trying to achieve here.
The issue I am having is that the following code will not print "blah" when I run test(). Instead if prints a nil, even if main() was executed first. How come updating of a Global variable's member property does not get reflected on itself at a different function ?
var GlobalMe SomeType
func main() {
for _,member := range GlobalMe.Members {
member.SomeProperty = "blah"
}
test()
}
func test() {
for _,member := range GlobalMe.Members {
fmt.Println("value:", member.SomeProperty)
}
}

If you have:
type SomeMemberType struct {
SomeProperty string
}
type SomeType struct {
Members []SomeMemberType
}
var GlobalMe SomeType
Simply change SomeType to:
type SomeType struct {
Members []*SomeMemberType
}
People often find this unintuitive, but it usually makes sense when you deal
with more basic types:
xs := []int{1,2,3}
for _, x := range xs {
x = 4
}
// xs is still {1,2,3}
This actually doesn't compile, but if it did xs wouldn't change. If you wanted
to modify the original you'd have to do:
xs := []int{1,2,3}
for i := range xs {
xs[i] = 4
}
// xs is now {4,4,4}
This behavior is common in most programming languages. Go is just a little more explicit about it by doing the same thing for structs. (So if you want java-like behavior use pointers)

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).

defining function inside of function

When defining a inner function which utilizes the variables of outer scope, should I pass the variables to the inner function as parameters?
In my example, generate and generate2 both give me same result, is there a reason I should choose any one of them?
The code picks key 1 to generate combinations with key 3,4,5,
then picks key 2 to generate combinations with key 3,4,5.
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello, playground")
src := map[int][]string{
1: []string{"1", "11", "111"},
2: []string{"2", "22"},
3: []string{"3"},
4: []string{"4"},
5: []string{"5", "55"},
}
result2 := generate2(src)
fmt.Println(result2)
result := generate(src)
fmt.Println(result)
}
func generate(src map[int][]string) []string {
var combo []string
var add = func(f []string) {
for _, v := range f {
for _, p := range src[3] {
for _, q := range src[4] {
for _, r := range src[5] {
combo = append(combo, v+p+q+r)
}
}
}
}
}
add(src[1])
add(src[2])
return combo
}
func generate2(src map[int][]string) []string {
var combo []string
var add = func(f []string, combo []string, src map[int][]string) []string {
for _, v := range f {
for _, p := range src[3] {
for _, q := range src[4] {
for _, r := range src[5] {
combo = append(combo, v+p+q+r)
}
}
}
}
return combo
}
combo = add(src[1], combo, src)
combo = add(src[2], combo, src)
return combo
}
When defining a inner function which utilizes the variables of outer scope, should I pass the variables to the inner function as parameters?
It depends on what you want to achieve.
What you call "a function inside a function" is actually called "a closure" (and some people call it "lambda").
Closures capture variables from the outer lexical scope, referenced in its body. In Go, this capturing is done "by reference" or "by name" which basically means each time a closure is called it will "see" current values of the variables it closes over, not the values these variables had at the time the closure was created—observe that the program:
package main
import (
"fmt"
)
func main() {
i := 42
fn := func() {
fmt.Println(i)
}
fn()
i = 12
fn()
}
would output
42
12
Conversely, when you pass values as arguments to calls to a closure, each call will see exactly the values passed to it.
I hope you now see that what strategy to pick largely depends on what you want.
Conceptually, you may think of a closure as being an instance of an ad-hoc anonymous struct data type, the fields of which are pointers to the variables the closure closes over, and each call to that closure being analogous to calling some (anonymous, sole) method provided by that type (actually, that's what the compiler usually does behind your back to implement a closure).
Such "method" may have arguments, and whether it should have them, and what should go to the type's fields and what should be that method's arguments can be judged using the usual approach you employ with regular types.
In this context, there is no functional difference between the two functions. As you noticed, local functions have access to local variables without explicitly passing them. In your example you might prefer to use generate1 for easier reading.

Function that takes map and only cares about key type

I have two maps, both of them are keyed by strings, but the values are of two different custom types.
map[string]type1
map[string]type2
Now I want to write a function which can take an argument of either of these two types, because that function only looks at the keys and doesn't care about the values at all. So I think it should look like this:
func takeTheMap(argument map[string]interface{}) {
...
But that doesn't work due to:
cannot use myVariable (type map[string]customType) as type map[string]interface {} in argument to takeTheMap
https://play.golang.org/p/4Xkhi4HekO5
Can I make that work somehow?
The only polymorphism in Go is interfaces. The only alternatives to that are reflection, duplication, or rethinking the broader design so that you don't need to do what you're trying to do here.
If the last option isn't a possibility, personally I would recommend duplication, since it's a whole four lines of code.
keys := make([]string, 0, len(myMap))
for key,_ := range myMap {
keys = append(keys,key)
}
A big complicated generic helper seems kind of unnecessary.
A solution using an interface. This example may seem a bit overkill and it may be better to in your case (I'm not sure, not enough details in your example) to just use a couple of for loops.
package main
import (
"fmt"
)
type foo bool
type bar string
type mapOne map[string]foo
type mapTwo map[string]bar
func (m mapOne) Keys() []string {
s := []string{}
for k := range m {
s = append(s, k)
}
return s
}
func (m mapTwo) Keys() []string {
s := []string{}
for k := range m {
s = append(s, k)
}
return s
}
type ToKeys interface {
Keys() []string
}
func main() {
m1 := mapOne{"one": true, "two": false}
m2 := mapTwo{"three": "foo", "four": "bar"}
doSomething(m1)
doSomething(m2)
}
func doSomething(m ToKeys) {
fmt.Println(m.Keys())
}
Playground example

Is there a way to write generic code to find out whether a slice contains specific element in Go?

I want to know is there a generic way to write code to judge whether a slice contains an element, I find it will frequently useful since there is a lot of logic to fist judge whether specific elem is already in a slice and then decide what to do next. But there seemed not a built-in method for that(For God's sake, why?)
I try to use interface{} to do that like:
func sliceContains(slice []interface{}, elem interface{}) bool {
for _, item := range slice {
if item == elem {
return true
}
}
return false
}
I thought interface{} is sort of like Object of Java, but apparently, I was wrong. Should I write this every time meet with a new struct of slice? Isn't there a generic way to do this?
You can do it with reflect, but it will be MUCH SLOWER than a non-generic equivalent function:
func Contains(slice, elem interface{}) bool {
sv := reflect.ValueOf(slice)
// Check that slice is actually a slice/array.
// you might want to return an error here
if sv.Kind() != reflect.Slice && sv.Kind() != reflect.Array {
return false
}
// iterate the slice
for i := 0; i < sv.Len(); i++ {
// compare elem to the current slice element
if elem == sv.Index(i).Interface() {
return true
}
}
// nothing found
return false
}
func main(){
si := []int {3, 4, 5, 10, 11}
ss := []string {"hello", "world", "foo", "bar"}
fmt.Println(Contains(si, 3))
fmt.Println(Contains(si, 100))
fmt.Println(Contains(ss, "hello"))
fmt.Println(Contains(ss, "baz"))
}
How much slower? about x50-x60 slower:
Benchmarking against a non generic function of the form:
func ContainsNonGeneic(slice []int, elem int) bool {
for _, i := range slice {
if i == elem {
return true
}
}
return false
}
I'm getting:
Generic: N=100000, running time: 73.023214ms 730.23214 ns/op
Non Generic: N=100000, running time: 1.315262ms 13.15262 ns/op
You can make it using the reflect package like that:
func In(s, e interface{}) bool {
slice, elem := reflect.ValueOf(s), reflect.ValueOf(e)
for i := 0; i < slice.Len(); i++ {
if reflect.DeepEqual(slice.Index(i).Interface(), elem.Interface()) {
return true
}
}
return false
}
Playground examples: http://play.golang.org/p/TQrmwIk6B4
Alternatively, you can:
define an interface and make your slices implement it
use maps instead of slices
just write a simple for loop
What way to choose depends on the problem you are solving.
I'm not sure what your specific context is, but you'll probably want to use a map to check if something already exists.
package main
import "fmt"
type PublicClassObjectBuilderFactoryStructure struct {
Tee string
Hee string
}
func main() {
// Empty structs occupy zero bytes.
mymap := map[interface{}]struct{}{}
one := PublicClassObjectBuilderFactoryStructure{Tee: "hi", Hee: "hey"}
two := PublicClassObjectBuilderFactoryStructure{Tee: "hola", Hee: "oye"}
three := PublicClassObjectBuilderFactoryStructure{Tee: "hi", Hee: "again"}
mymap[one] = struct{}{}
mymap[two] = struct{}{}
// The underscore is ignoring the value, which is an empty struct.
if _, exists := mymap[one]; exists {
fmt.Println("one exists")
}
if _, exists := mymap[two]; exists {
fmt.Println("two exists")
}
if _, exists := mymap[three]; exists {
fmt.Println("three exists")
}
}
Another advantage of using maps instead of a slice is that there is a built-in delete function for maps. https://play.golang.org/p/dmSyyryyS8
If you want a rather different solution, you might try the code-generator approach offered by tools such as Gen. Gen writes source code for each concrete class you want to hold in a slice, so it supports type-safe slices that let you search for the first match of an element.
(Gen also offers a few other kinds of collection and allows you to write your own.)

Refactor function to make it reusable across types in Go

I have a function that initializes an array of structs from an array of an array of values. This is how I'm doing it currently:
type Loadable interface {
Load([]interface{})
}
type FooList struct {
Foos []*Foo
}
func (fl *FooList) Load(vals []interface{}) {
fl.Foos = make([]*Foo, len(vals))
for i, v := range vals {
foo := &Foo{}
foo.Load(v.([]interface{}))
fl.Foos[i] = foo
}
}
This works just fine, but now I also need to initialize BarLists and BazLists which contain Bars and Bazs. Instead of sprinkling the same snippet throughout my code which all look like this:
type BarList struct {
Bars []*Bar
}
func (fl *BarList) Load(vals []interface{}) {
fl.Bars = make([]*Bar, len(vals))
for i, v := range vals {
bar := &Bar{}
bar.Load(v.([]interface{}))
fl.Bars[i] = bar
}
}
What's the correct way to refactor this code to make it more DRY?
The code you show does not violate the DRY principle. The code implementing the Loader interface (I refuse to write the javaism you used) for type FooList and BarList shares only one line - the range statement. Otherwise they're type specific.
As Go has no generics, there's no direct way how to not write type specialized versions in a generic way (modulo poor choices like everything is an interface{} etc. and/or slowing down your code 10 times by using reflection.)
The simplest I can come up with using reflection would be something like this (not tested):
import "reflect"
// example_of_type should be an instance of the type, e.g. Foo{}
// returns slice of pointers, e.g. []*Foo
func Load(vals []interface{}, example_of_type interface()) interface{} {
type := reflect.TypeOf(example_of_type)
list := reflect.MakeSlice(type.PtrOf().SliceOf(), len(vals), len(vals))
for i, v := range vals {
bar := reflect.New(type)
bar.Interface().(Loadable).Load(v.([]interface{}))
list.Index(i).Set(bar)
}
return list.Interface()
}
You would use it like:
fl.Foos = Load(vals, Foo{}).([]*Foo)
fl.Bars = Load(vals, Bar{}).([]*Bar)

Resources