Adding struct pointers to slice of interface pointers - pointers

I have an interface and a struct implementing it:
package main
import "fmt"
type Vehicle interface {
GetColor() string
SetColor(color string)
}
type Car struct {
Color string
}
func (car *Car) SetColor(color string) {
car.Color = color
}
func (car *Car) GetColor() string {
return car.Color
}
func NewCar(color string) *Car {
car := new(Car)
car.Color = color
return car
}
func main() {
car := NewCar("red")
vehicles := make([]Vehicle, 0)
vehicleSelection := make([]*Vehicle, 0)
vehicles = append(vehicles, car)
vehicleSelection = append(vehicleSelection, car) //DOES NOT WORK!
for _, vehicle := range vehicleSelection {
vehicle.SetColor("blue") //DOES NOT WORK!
}
for _, vehicle := range vehicles {
fmt.Println(vehicle.GetColor())
}
}
I want to have a subset (vehicleSelection slice) of all my vehicles (vehicles slice). All changes made to vehicles in the vehicleSelectionslice must also be reflected by the vehicles in the vehicles slice. Therefore I want the vehicleSelection slice to be a slice of pointers. How can I add cars to this slice?

Related

Modifying a struct slice within a struct in Go

In the following example, a person has a slice of friendships, and I try to initialize a friendship as a pointer to another person object, but for some reason it fails, and the result is that nobody has any friendships. Am I not using a pointer somewhere where I should be?
package main
import (
"fmt"
"math/rand"
)
type friendship struct {
friend *person
}
type person struct {
name int
friendship []friendship
}
func createPerson(id int) person {
return person{id, make([]friendship, 0)}
}
func (p *person) addFriends(possibleFriends []*person, numFriends int) {
var friend *person
for i := 0; i < numFriends; i++ {
friend = possibleFriends[rand.Intn(len(possibleFriends))]
p.friendship = append(p.friendship, friendship{friend})
}
}
func main() {
numPeople := 20
people := make([]person, numPeople)
possibleFriends := make([]*person, numPeople)
for i := 0; i < numPeople; i++ {
people[i] = createPerson(i)
possibleFriends[i] = &(people[i])
}
for _, p := range people {
p.addFriends(possibleFriends, 2)
}
fmt.Println(people)
}
use
for i := 0; i < numPeople; i++ {
people[i].addFriends(possibleFriends, 2)
}
or
for i, _ := range people {
people[i].addFriends(possibleFriends, 2)
}
instead of
for _, p := range people {
p.addFriends(possibleFriends, 2)
}
this is because p is a copy of people[i], addFriends has no effect on slice people

Is there a more generic way to do this function?

I would like to make this function more generic (with a "for")
func (e example) ScanRow(rows *sql.Rows) (example, error) {
val := reflect.ValueOf(e)
test := make([]interface{}, val.Type().NumField())
test[0] = &e.Id
test[1] = &e.CreatedAt
test[2] = &e.Text
test[3] = &e.AuthorId
test[4] = &e.CategoryId
if err := rows.Scan(test[0], test[1], test[2], test[3], test[4]); err != nil {
return e, err
}
return e, nil
}
Here is the struct example:
type example struct {
Id int `json:"id"`
CreatedAt string `json:"created_at"`
Text string `json:"text"`
AuthorId int `json:"author_id"`
CategoryId int `json:"category_id"`
}
Do you think it's possible ? I am trying to find a way to do that but i am lost...

How to implement GetStringValueByField(n interface{}, field_name string) string

I am trying to implement a method to get a value from a arbitrary struct-field as a string given by the struct and the fieldname as a string.
With reflect it is always panicing.
panic: reflect: call of reflect.Value.FieldByName on interface Value
goroutine 16 [running]
// attempt to implement GetStringValueByFieldName()
package main
import "fmt"
import "reflect"
import "strconv"
func main() {
a:=Order{A:"asdf", B:123}
fmt.Println(a)
fmt.Println(Test1(a, "A"))
fmt.Println(Test1(a, "B"))
}
type Order struct {
A string
B int64
}
func Test1 (n interface{}, field_name string) string {
var x string
s := reflect.ValueOf(&n).Elem()
x, ok := s.FieldByName(field_name).Interface().(string)
if ok {
fmt.Println(ok)
}
return x
}
func GetStringValueByFieldName(n interface{}, field_name string) string {
ps := reflect.ValueOf(&n)
// struct
s := ps.Elem()
if s.Kind() == reflect.Struct {
f := s.FieldByName(field_name)
if f.IsValid() {
if f.CanSet() {
if f.Kind() == reflect.Int {
return strconv.FormatInt(f.Int(),10)
}
if f.Kind() == reflect.String {
return f.String()
}
}
}
}
return ""
}
Here's how to get a string field by name:
package main
import (
"fmt"
"reflect"
)
func main() {
a := Order{A: "asdf", B: 123}
fmt.Println(a)
fmt.Println(GetStringValueByFieldName(a, "A"))
fmt.Println(GetStringValueByFieldName(&a, "A"))
fmt.Println(GetStringValueByFieldName(a, "B"))
fmt.Println(GetStringValueByFieldName(0, "B"))
fmt.Println(GetStringValueByFieldName(a, "C"))
}
type Order struct {
A string
B int64
}
func GetStringValueByFieldName(n interface{}, field_name string) (string, bool) {
s := reflect.ValueOf(n)
if s.Kind() == reflect.Ptr {
s = s.Elem()
}
if s.Kind() != reflect.Struct {
return "", false
}
f := s.FieldByName(field_name)
if !f.IsValid() {
return "", false
}
switch f.Kind() {
case reflect.String:
return f.Interface().(string), true
case reflect.Int:
return strconv.FormatInt(f.Int(), 10), true
// add cases for more kinds as needed.
default:
return "", false
// or use fmt.Sprint(f.Interface())
}
}
playground

How can go-lang curry?

In functional programming likes Haskell, I can define function
add a b = a+b
Then add 3 will return a function that take one parameter and will return 3 + something
How can I do this in GO?
When I define a function that take more than one (say n) parameters, can I only give it one parameter and get another function that take n-1 parameters?
Update:
Sorry for the imprecise words in my original question.
I think my question should be asked as two qeustions:
Is there partial application in GO?
How GO do function curry?
Thanks TheOnly92 and Alex for solving my second question. However, I am also curious about the first question.
To extend on the previous answer, which allows you to take an arbitrary number of arguments:
package main
import (
"fmt"
)
func mkAdd(a int) func(...int) int {
return func(b... int) int {
for _, i := range b {
a += i
}
return a
}
}
func main() {
add2 := mkAdd(2)
add3 := mkAdd(3)
fmt.Println(add2(5,3), add3(6))
}
Perhaps something like
package main
import (
"fmt"
)
func mkAdd(a int) func(int) int {
return func(b int) int {
return a + b
}
}
func main() {
add2 := mkAdd(2)
add3 := mkAdd(3)
fmt.Println(add2(5), add3(6))
}
You can take it a step further by defining a function type and then adding a method to it.
package main
import "fmt"
type Add func(int, int) int
func (f Add) Apply(i int) func(int) int {
return func(j int) int {
return f(i, j)
}
}
func main() {
var add Add = func(i, j int) int { return i + j }
add3 := add.Apply(3)
fmt.Println("add 3 to 2:", add3(2))
}
You can even try with variadic functions:
package main
import "fmt"
type Multiply func(...int) int
func (f Multiply) Apply(i int) func(...int) int {
return func(values ...int) int {
values = append([]int{i}, values...)
return f(values...)
}
}
func main() {
var multiply Multiply = func(values ...int) int {
var total int = 1
for _, value := range values {
total *= value
}
return total
}
var times2 Multiply = multiply.Apply(2)
fmt.Println("times 2:", times2(3, 4), "(expect 24)")
// ... and you can even cascade (if assigned the Multiply type)
times6 := times2.Apply(3)
fmt.Println("times 6:", times6(2, 3, 5, 10), "(expect 1800)")
}
Hope this helps!

Using a map for its set properties with user defined types

I'm trying to use the built-in map type as a set for a type of my own (Point, in this case). The problem is, when I assign a Point to the map, and then later create a new, but equal point and use it as a key, the map behaves as though that key is not in the map. Is this not possible to do?
// maptest.go
package main
import "fmt"
func main() {
set := make(map[*Point]bool)
printSet(set)
set[NewPoint(0, 0)] = true
printSet(set)
set[NewPoint(0, 2)] = true
printSet(set)
_, ok := set[NewPoint(3, 3)] // not in map
if !ok {
fmt.Print("correct error code for non existent element\n")
} else {
fmt.Print("incorrect error code for non existent element\n")
}
c, ok := set[NewPoint(0, 2)] // another one just like it already in map
if ok {
fmt.Print("correct error code for existent element\n") // should get this
} else {
fmt.Print("incorrect error code for existent element\n") // get this
}
fmt.Printf("c: %t\n", c)
}
func printSet(stuff map[*Point]bool) {
fmt.Print("Set:\n")
for k, v := range stuff {
fmt.Printf("%s: %t\n", k, v)
}
}
type Point struct {
row int
col int
}
func NewPoint(r, c int) *Point {
return &Point{r, c}
}
func (p *Point) String() string {
return fmt.Sprintf("{%d, %d}", p.row, p.col)
}
func (p *Point) Eq(o *Point) bool {
return p.row == o.row && p.col == o.col
}
package main
import "fmt"
type Point struct {
row int
col int
}
func main() {
p1 := &Point{1, 2}
p2 := &Point{1, 2}
fmt.Printf("p1: %p %v p2: %p %v\n", p1, *p1, p2, *p2)
s := make(map[*Point]bool)
s[p1] = true
s[p2] = true
fmt.Println("s:", s)
t := make(map[int64]*Point)
t[int64(p1.row)<<32+int64(p1.col)] = p1
t[int64(p2.row)<<32+int64(p2.col)] = p2
fmt.Println("t:", t)
}
Output:
p1: 0x7fc1def5e040 {1 2} p2: 0x7fc1def5e0f8 {1 2}
s: map[0x7fc1def5e0f8:true 0x7fc1def5e040:true]
t: map[4294967298:0x7fc1def5e0f8]
If we create pointers to two Points p1 and p2 with the same coordinates they point to different addresses.
s := make(map[*Point]bool) creates a map where the key is a pointer to the memory allocated to a Point and the value is boolean value. Therefore, if we assign elements p1 and p2 to the map s then we have two distinct map keys and two distinct map elements with the same coordinates.
t := make(map[int64]*Point) creates a map where the key is a composite of the coordinates of a Point and the value is a pointer to the Point coordinates. Therefore, if we assign elements p1 and p2 to the map t then we have two equal map keys and one map element with the shared coordinates.

Resources