Suppose, I am writing a minesweeper game, and i have a struct to hold the game field, that contains a 2D array with mines. Suppose, i want to initialize it with some mines. Is there a way to say gameField GameField = new(GameField, 30), similar to what i'd do in java?
Here is some code to illustrate my point:
type GameField struct {
field [20][20] int
}
func (this *GameField) scatterMines(numberOfMines int) {
//some logic to place the numberOfMines mines randomly
}
What i want is to call an initializer and have that scatterMines func executed automatically.
A pattern I've seen in Go structs is a corresponding NewXxx method (e.g., image pkg):
type GameField struct {
field [20][20] int
}
func NewGameField(numberOfMines int) *GameField {
g := new(GameField)
//some logic to place the numberOfMines mines randomly
//...
return g
}
func main() {
g := NewGameField(30)
//...
}
Go objects have no constructors, so there is no way to have scatterMines function executed automatically at variable initialization. You need to call the method explicitly:
var GameField g
g.scatterMines(30)
See also http://golang.org/ref/spec#The_zero_value.
Related
I have many struct that pass as pointer to a function called AutoFilled. each struct is different from another. but some field are the same such as "creator", "createon", "edition"..,
Is there any way to change common field in AutoFilled function?
package main
import (
"fmt"
"time"
)
type User struct {
ID string
Creator string
CreateOn time.Time
Edition int
Name string
Password string
}
type Book struct {
ID string
Creator string
CreateOn time.Time
Edition int
Name string
ISBN string
}
func AutoFilled(v interface{}) {
// Add Creator
// Add CreateOn
// Add Edition (Version) [new is zero, edit increase 1]
}
func main() {
user := User{}
book := Book{}
AutoFilled(&user)
AutoFilled(&book)
fmt.Println(user)
fmt.Println(book)
fmt.Println("Thanks, playground")
}
It looks like you just need a Common struct embedded (sometimes called mixin) in the other structs.
type Common struct {
ID string
Creator string
CreateOn time.Time
Edition int
}
type User struct {
Common
Name string
Password string
}
type Book struct {
Common
Name string
ISBN string
}
Also I would make the AutoFilled function a method on Common. (Using an interface you lose type safety.)
func (c *Common)Autofill() {
// set fields on Common struct
}
func main() {
user := &User{}
user.Autofill()
#AJR has given a very good option. here is an alternative approach.
For each struct (Book and User), create a method called New<StructName. Taking Book as an example
func NewBook() *Book {
return &Book {
//you can fill in default values here for common construct
}
}
You can further extend this pattern by creating a Common struct and pass in that object to NewBook when you are creating it i.e.,
func NewBook(c Common) *Book {
return &Book {
Common: c
//other fields here if needed
}
}
Now in your main code, you will do this
func main() {
c := NewCommon() //this method can create common object with default values or can take in values and create common object with those
book := NewBook(c)
//now you don't need autofill method
fmt.Println("Thanks, playground")
}
For example
var myStructRef *Vertex
var myStruct Vertex
myStructRef = &Vertex{2, 3}
myStruct = Vertex{2, 3}
fmt.Println(myStructRef)
fmt.Println(myStruct)
changeByReferenceStruct(myStructRef)
changeByValueStruct(myStruct)
fmt.Println(myStructRef)
fmt.Println(myStruct)
And
func changeByValueStruct(myStruct Vertex) {
myStruct.X = 5
fmt.Println(myStruct)
}
func changeByReferenceStruct(myStruct *Vertex) {
myStruct.X = 7
fmt.Println(myStruct)
}
Isn't both myStructRef *Vertex and myStruct Vertex a pointer pointing to the struct itself? Why is there a discrepancy in behavior when I modify the struct in a function?
Is golang creating a new struct in changeByValueStruct when it resolves the parameter?
When you pass a pointer as an argument, what happens under the hood is that a copy of that pointer is created and passed to the underlying function. It should not be confused with pass-by-reference.
Let's look at an example to better grasp it:
package main
import (
"fmt"
)
type Point struct {
x int
y int
}
func (p Point) String() string {
return fmt.Sprintf("(%d, %d)", p.x, p.y)
}
func modifyValue(point Point) {
point.x += 10
}
func modifyPointer(point *Point) {
point.x = 5
point.y = 5
}
func modifyReference(point *Point) {
point = &Point{5, 5}
}
func main() {
p := Point{0, 0}
fmt.Println(p) // prints (0, 0)
modifyValue(p)
fmt.Println(p) // prints (0, 0)
modifyPointer(&p)
fmt.Println(p) // prints (5, 5)
p = Point{0, 0}
modifyReference(&p)
fmt.Println(p) // prints (0, 0)
}
What happens inside the modifyValue function is that a totally different instance of a Point structure is modified, so the value passed when calling the function is unaffected.
In the second example, a pointer to the structure is passed so the fields of the structure can be modified in a way that is visible from outside.
The most interesting point is made by the last function, modifyReference. If you are familiar with the pass by reference paradigm available in other languages you would expect to be able to modify the referenced object altogether, but this doesn't happen. It's because you're modifying a copy of the pointer passed as argument.
You may wonder, if everything is passed by value, when should you pass pointers and when values. Passing values assures the caller function that the passed structure cannot suffer any changes, so when you need this behaviour, go for the value. The downside of this is that a copy of the entire object is made and, if it is too big, memory becomes a concern.
If you're passing a big structure as an argument, using a pointer is better because it saves space, but you lose the guarantee that the object won't suffer any changes.
Passing struct to function argument makes copy of values. And passing pointer of struct doesn't. So passing struct can't update field value.
package main
import (
"fmt"
)
type Foo struct {
value int
}
func PassStruct(foo Foo) {
foo.value = 1
}
func PassStructPointer(foo *Foo) {
foo.value = 1
}
func main() {
var foo Foo
fmt.Printf("before PassStruct: %v\n", foo.value)
PassStruct(foo)
fmt.Printf("after PassStruct: %v\n", foo.value)
fmt.Printf("before PassStructPointer: %v\n", foo.value)
PassStructPointer(&foo)
fmt.Printf("after PassStructPointer: %v\n", foo.value)
}
https://play.golang.org/p/AM__JwyaJa
This is a very straight forward question.
How do you implement Initialize() below with reflect?
Or is this possible?
func Initialize(v interface{}) {
// ... some reflection code
}
type MyType struct {
Name string
}
func main() {
var val *MyType
// val is nil before initialize
Initialize(val)
// val is now &MyType{Name: ""}
// ...
}
```
Here's how to do it:
func Initialize(v interface{}) {
rv := reflect.ValueOf(v).Elem()
rv.Set(reflect.New(rv.Type().Elem()))
}
This function must be called with a pointer to the value to set:
Initialize(&val)
playground example
The code in this answer panics if the argument type is not a pointer to a pointer. Depending on your use, you might want to check the reflect value kind before calling Elem().
I am writing a simple game in Go and have some problems with it. My, cut off, code looks like this:
package main
import "fmt"
type Location struct {
X int
Y int
}
type Car struct {
MaxSpeed int
Loc Location
}
func (car Car) SetLocation(loc Location) {
car.Loc = loc
}
func (car Car) GetLocation() Location {
return car.Loc
}
type Bike struct {
GearsNum int
Loc Location
}
func (bike Bike) SetLocation(loc Location) {
bike.Loc = loc
}
func (bike Bike) GetLocation() Location {
return bike.Loc
}
type Movable interface {
GetLocation() Location
SetLocation(Location)
}
type Fleet struct {
vehicles []Movable
}
func (fleet *Fleet) AddVehicles(v ...Movable) {
for _, x := range(v) {
fleet.vehicles = append(fleet.vehicles, x)
}
}
func (fleet *Fleet) WherTheyAre() {
for _, v := range(fleet.vehicles) {
fmt.Println(v.GetLocation())
}
}
func main() {
myCar := Car{MaxSpeed: 200, Loc: Location{12, 34}}
myBike := Bike{GearsNum: 11, Loc: Location{1, 1}}
myFleet := Fleet{}
myFleet.AddVehicles(myCar)
myFleet.AddVehicles(myBike)
myFleet.WherTheyAre()
myCar.SetLocation(Location{0,0})
myFleet.WherTheyAre()
}
The assumption is that Car and Bike are very big structures which I do not want to copy. How should I design the code to be able to modify the location of the car which is the part of the Fleet? Other words how to design the Fleet struct to be able to modify its movable objects?
I have tried to experiment with pointers to interfaces but I was not good idea...
Thanks for help!
The problem is that you've defined the method with value receivers. When you call a method on a receiver the receiving type is actually being passed as an argument, in this case by value and you're modifying that copy.
func (bike Bike) SetLocation(loc Location) {
bike.Loc = loc // modifies local copy of Bike
}
func (bike *Bike) SetLocation(loc Location) {
bike.Loc = loc // modifies the referenced bike
}
You gotta declare your types differently though, or use the & operator in order to call these methods because you have value types in your main. My preference is to use this syntax bike := &Bike{} in almost all cases. I will only go away from it if I have a convenience method for initilization or a very specific reason for using a value type (which is extremely rare).
But basically, you can't make a setter use a value type receiver. If you want to use these structs as value types I would recommend exporting the fields so they can be accessed without getter or setter. Also, just regarding style, I would be displeased to see the use of getters and setters at all unless you actually are abstracting some logic. There's no point in not exporting a field if you're going to provide a setter that directly assigns the value passed in to said field. Also, wasn't looking to closely but you are exporting all fields on your structs so your setters are useless and most programmers would just do bike.Loc = anythingIWantBecauseThisFieldsExportedWhichYouMayThinkOfAsPublic
I'd like to declare a map that would that would look like this, so I could map various init functions to initType:
func makeMap(){
m := make(map[initType]&InitFunc)
//How should the value declaration be set up for this map?
}
type initType int
const(
A initType = iota
B
C
D
)
func init(aInitType initType){
doStuff(aInitType)
}
func init(aInitType initType){
doOtherStuff(aInitType)
}
func init(aInitType initType){
doMoreStuff(aInitType)
}
How do I declare the function pointer type (which I called &InitFunc in the example because I don't know how to do it) so I can use it as the value in a Map?
Unlike C, you don't actually need a "pointer" to the function, since in Go, functions are reference types, similar to slices, maps, and channels. Further, the address operator, &, produces a pointer to a value, but to declare a pointer type, use *.
You seem to be wanting your InitFunc to take a single InitType and return no values. In that case, you would declare it as:
type InitFunc func(initType)
Now, your map initialization can simply look like:
m := make(map[initType]InitFunc)
A complete example would be (http://play.golang.org/p/tbOHM3GKeC):
package main
import "fmt"
type InitFunc func(initType)
type initType int
const (
A initType = iota
B
C
D
MaxInitType
)
func Init1(t initType) {
fmt.Println("Init1 called with type", t)
}
var initFuncs = map[initType]InitFunc{
A: Init1,
}
func init() {
for t := A; t < MaxInitType; t++ {
f, ok := initFuncs[t]
if ok {
f(t)
} else {
fmt.Println("No function defined for type", t)
}
}
}
func main() {
fmt.Println("main called")
}
Here, it's looping through each initType, and calling the applicable function, if it is defined.