I'm a bit confused as to why this happens when attempting to remove an element from a slice in Go.
As a simplified example, I have the following data structures:
type Person struct {
Name string
}
type People []Person
I want to add a method to remove a person with a certain name from the list of people with people.Remove("Sam"):
func (p *People) Remove(name string) {
for i, person := range *p {
if person.Name == name {
// Doesn't work
*p = append(*p[:i], *p[i+1:]...)
}
}
}
I thought this would work, but referencing the slice elements in this manner returns a compile error: cannot slice p (type *People).
So, fair enough. But when I set *p to another variable (a), it works exactly as expected:
func (p *People) Remove(name string) {
for i, person := range *p {
if person.Name == name {
// Does work
a := *p
*p = append(a[:i], a[i+1:]...)
}
}
}
Why do I need to set the slice to a difference variable before this method works? Shouldn't the behaviour be exactly the same?
I'm probably misunderstanding something fundamental here so if anyone can explain why this is required I'd love to know. Thank you!
The slice expressions in *p = append(*p[:i], *p[i+1:]...) take precedence over the * operator. You need to enclose those in parentheses.
func (p *People) Remove(name string) {
for i, person := range *p {
if person.Name == name {
// Doesn't work
*p = append((*p)[:i], (*p)[i+1:]...)
}
}
}
https://play.golang.org/p/cbT65mCzA4h
Related
In Go, I'm trying to pass an interface{} to the statement.Exec() function from go-sqlite3. I'm sure this is a solved problem, but I cannot figure it out.
Basically I have a struct with the row data which I want to pass to a function that will insert it to a sqlite db. The thing is I want to be able to programmatically control what goes into the statement.Exec() function
Here is an excerpt:
type hostRows struct {
domain string
}
type clientRows struct {
name string
}
func main() {
...
data := hostRows{domain: "dom.com"}
insertRow(sqliteDatabase, data)
data2 := clientRows{name: "bob"}
insertRow(sqliteDatabase, data2)
...
}
func insertRow(db *sql.DB, row interface{}) {
insertSQL := "INSERT INTO table(col) VALUES (?)"
statement, _ := db.Prepare(insertSQL)
statement.Exec(row) // here's the issue, how can I extract the element in the interface to pass it to the function for Exec to understand
}
I know that in this example, I could hard code the row type to the struct and type statement.Exec(row.(hostRows).domain), but now the code will break to when the client struct is passed.
here is the deceleration for the Exec function
func (s *Stmt) Exec(args ...interface{}) (Result, error)
I've tried playing with reflect but it hasn't worked for me so far.
My only solution for the moment is using a switch condition that could check and prepare the right command for Exec, but this is less than dodgy.
type hostRows struct {
domain string
}
type clientRows struct {
name string
}
func main() {
...
data := hostRows{domain: "dom.com"}
insertRow(sqliteDatabase, 1, data)
data2 := clientRows{name: "bob"}
insertRow(sqliteDatabase, 2, data2)
...
}
func insertRow(db *sql.DB, i int, row interface{}) {
insertSQL := "INSERT INTO table(col) VALUES (?)"
statement, _ := db.Prepare(insertSQL)
// This basically could be a working solution, but I'm sure there is a better one
switch i {
case 1:
data := row.(hostRows)
statement.Exec(data.domain)
case 2:
data := row.(clientRows)
statement.Exec(data.name)
}
}
edit: corrected the INSERT statement ; forget the columns. corrected statement.Exec(row.domain) to statement.Exec(row.(hostRows).domain)
edit2: added second example
Remember that in order for reflect.Interface() to work, you must export the fields. To achieve what you want using reflection, you could try something like this:
type hostRows struct {
//Should export field to read it using reflect.Value.Interface()
Domain string
}
type clientRows struct {
//Should export field to read it using reflect.Value.Interface()
Name string
}
func insertRow(db *sql.DB, i int, row interface{}) {
rv := reflect.ValueOf(row)
var args []interface{}
for i := 0; i < rv.NumField(); i++ {
args = append(args, rv.Field(i).Interface())
}
db.Exec("Insert Satement...", args...)
}
So basically I was wondering if it possible in GO, because I was playing with Dereference.
For example in Code shown below. Pointer is passed to function and I'm trying to return one letter of passed pointer string, in given example that is H, but however slice can only be used with strings. And I was wondering if it possible to do this using pointer Dereference.
Code Example:
func Test(test *string) {
if len(*test) > 0 {
*test = *test[:1]
}
strings.ToUpper(*test)
}
func main() {
str := "hello"
Test(&str)
fmt.Print( str)
}
Is it possible in Go to pass pointer of string and make it slice of string?
Yes: func (ps *string) []string { return []string{*ps} }
You need to place test in brackets, i.e. dereference the pointer first, and then slice it.
Then the Test function still wouldn't return capital H though, because ToUpper takes and returns a value. So you need to reassign the output of ToUpper to *test as well:
func Test(test *string) {
if len(*test) > 0 {
*test = (*test)[:1] // bracketed `test`
}
*test = strings.ToUpper(*test) // reassign to `test`
}
func main() {
str := "hello"
Test(&str)
fmt.Print(str) // Prints 'H'
}
Go Play example
I have the following structure in Golang
type mystruct struct {
Name string
Power int
}
My purpose is to write a function that takes as input a slice of type *mystuct and returns a slice of type int containing the "Power" property taken from the input slice.
my code is presented below:
package main
import (
"fmt"
)
func main() {
obj := make([]*mystruct, 15)
for i, s := range obj {
s.Power = i
}
fmt.Println(extractpowers(obj))
}
func extractpowers(obj []*mystruct) []int {
powers := make([]int, len(obj))
for i, s := range obj {
powers[i] = s.Power
}
return powers
}
My issue is that the obj := make([]*mystruct, 15) creates a slices of 15 *mystruc pointers initialized to nil; which causes the code within the for loop to raise a panic of type "invalid memory or nil pointer dereference".
My question is what is the proper and fastest way to initialize the slice; (the equivalent of var lst = new List(Of mystruct) in .net)
Regards.
Use a composite literal and take its address in the loop:
for i := range obj {
obj[i] = &mystruct{Power: i}
}
Try it on the Go Playground.
I have a function which accepts slice of values and fields as a set of optional parameters and the function maps each value to a field and returns error if any to the caller as in below
func Unmarshall(source []interface{}, dest ...interface{}) error {
if len(source) != len(dest) {
return errors.New("source and destination doesn't match")
}
for i, s := range source {
dest[i] = s
}
return nil
}
and below the code I have for the caller
for _, r := range rows.Values {
item := entity.Item{}
e :=Unmarshall(r,
&item.Name,
&item.Description,
&item.AddedUTCDatetime,
&item.ModifiedUTCDatetime)
if e == nil {
items = append(items, item)
}
}
But the issue with the above is item.Name,item.Description, &item.AddedUTCDatetime, &item.ModifiedUTCDatetime doesn't retain the values set in the Unmarshall func even though I passed in the pointer to the fields.
Is there anything wrong with the above code?
Is there anything wrong with the above code?
Yes. You're discarding the pointers and are simply overwriting them with new values. To set value that pointer points to, you must dereference it. Could look something like this in your case:
for i, s := range source {
str, ok := dest[i].(*string)
if ok {
*str = s.(string)
}
}
This one takes care of all types
for i, s := range source {
so := reflect.ValueOf(s)
if !reflect.DeepEqual(so, reflect.Zero(reflect.TypeOf(so)).Interface()) {
reflect.ValueOf(dest[i]).Elem().Set(so)
}
}
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