Below code is Map implementation using array, slice & pointers:
package gomap
import "fmt"
type Entry struct {
stockName string
stockValue float64
}
type bucket []Entry
type Map [4]bucket
type bucketElementPosition [4]int
var emptyPosition = bucketElementPosition{0, 0, 0, 0}
func Newmap() Map {
return Map{} // [(nil,0,0), (nil,0,0), (nil,0,0), (nil,0,0)]
}
func (m *Map) Lookup(key string) float64 {
bucketNumber := (key[0] - 'A') / 7
for _, entry := range m[bucketNumber] { // (*m)[bucketNumber]
if entry.stockName == key {
return entry.stockValue
}
}
return 0
}
func (m *Map) Insert(key string, value float64) {
bucketNumber := (key[0] - 'A') / 7
if cap(m[bucketNumber]) == 0 { // (*m)[bucketNumber]
fmt.Println("bucket number:", bucketNumber)
m[bucketNumber] = make([]Entry, 0, 100)
}
m[bucketNumber] = append(m[bucketNumber], Entry{key, value})
emptyPosition[bucketNumber]++
}
package main
import (
"fmt"
"github.com/myhub/cs61a/gomap"
)
func main() {
var stockData = gomap.Newmap()
(&stockData).Insert("AAPL", 94.56)
(&stockData).Insert("HSCO", 26.72)
(&stockData).Insert("NMZN", 697.45)
(&stockData).Insert("ZSFT", 50.81)
(&stockData).Insert("PMGN", 150.83)
fmt.Println((&stockData).Lookup("AAPL"))
fmt.Println((&stockData).Lookup("HSCO"))
fmt.Println((&stockData).Lookup("NMZN"))
fmt.Println((&stockData).Lookup("ZSFT"))
fmt.Println((&stockData).Lookup("PMGN"))
}
Code smell bucketNumber := (key[0] - 'A') / 7 can be taken care by reading bits and hash.
but for line type bucket []Entry
How to make the concrete type Map, Entry type agnostic? because key is fixed as string and value is fixed as float64
I completed the home assignment like this:
package gomap
import "fmt"
type Entry struct {
key, value interface{}
}
type Map struct {
buckets [4][]Entry
}
func Newmap() *Map {
return &Map{}
}
func (m *Map) bucketNumber(key interface{}) int {
s := fmt.Sprint(key)
return int(s[0]) % len(m.buckets)
}
func (m *Map) Lookup(key interface{}) interface{} {
bucketNumber := m.bucketNumber(key)
for _, entry := range m.buckets[bucketNumber] {
if entry.key == key {
return entry.value
}
}
return nil
}
func (m *Map) Insert(key interface{}, value interface{}) {
bucketNumber := m.bucketNumber(key)
m.buckets[bucketNumber] = append(m.buckets[bucketNumber], Entry{key, value})
}
https://play.golang.org/p/KmVSeDavc3y
There are a few ways you can do that. The most obvious is to use interface{} for key and value. However, there's a type-safe way of doing the keys. You can make Key an interface:
type Key interface {
// Returns the bucket number for the key
BucketNumber() int
// Eq compares the key with the given key
Eq(Key) bool
}
Then you can have an Entry using this key:
type Entry struct {
k Key
v interface{}
}
You can rewrite the map functions to use this key. Value would have to be an interface, and you have to use type assertions to get the underlying value.
Related
I want to achieve polymorfism by passing a pointer to a slice of a speficic interface to a function, and update the slice inside of the function. It works quite well with interface{}
package main
import (
"fmt"
"strconv"
)
type valuer interface {
value() string
}
type myInt int
func (i myInt) value() string {
return strconv.Itoa(int(i))
}
func values(vals interface{}) {
res, ok := vals.(*[]myInt)
if !ok {
panic("wrong type")
}
*res = []myInt{1, 2, 3}
}
func main() {
var a []myInt
values(&a)
for _, b := range a {
fmt.Println(b.value())
}
}
Go Playground
However if I try to change interface{} to a pointer to a slice of a specific interface it does not work:
package main
import (
"fmt"
"strconv"
)
type valuer interface {
value() string
}
type myInt int
func (i myInt) value() string {
return strconv.Itoa(int(i))
}
func values(vals *[]valuer) {
*vals = []myInt{1, 2, 3}
}
func main() {
var a []myInt
values(&a)
for _, b := range a {
fmt.Println(b.value())
}
}
Go Playground
returning an error
./prog.go:19:8: cannot use []myInt literal (type []myInt) as type []valuer in assignment
./prog.go:24:9: cannot use &a (type *[]myInt) as type *[]valuer in argument to values
What am I doing wrong?
From the insights provided by #kostix, I can see that I cannot keep both -- a restriction of a non-empty interface, and a simplicity of passing a pointer of a slice of a concrete type. So if I do want to keep the output as a slice of non-empty interfaces, I can do something of this sort instead:
package main
import (
"fmt"
"strconv"
)
type valuer interface {
value() string
}
type myInt int
func (i myInt) value() string {
return strconv.Itoa(int(i))
}
func values() []valuer {
res := make([]valuer, 3)
c := []myInt{1, 2, 3}
for i, v := range c {
res[i] = v
}
return res
}
func main() {
a := values()
for _, b := range a {
fmt.Println(b.value())
}
}
Go Playground
It would keep api simpler to use, and allow polymorphism with non-empty interfaces for the output.
One inconvenience for the users with this approach, they will have to "unbox" members of the slice if they want to use methods of a concrete type that are not specified by the interface.
I am writing a program which has several structs and functions to handle these structs differently. I am having a generic function which calls the required function based on the inputs. Is there a generic way to use the returned value from getStruct()?
package main
var X func(s []string) A
var Y func(s []string) B
type A struct {
Name string
Place string
}
type B struct {
Name string
Place string
Value string
}
func newA(s []string) A {
a := A{
Name: s[0],
Place: s[1],
}
return a
}
func newB(s []string) B {
a := B{
Name: s[0],
Place: s[1],
Value: s[2],
}
return a
}
func getStruct(t string) interface{} {
switch {
case t == "A":
return X
case t == "B":
return Y
default:
return //someStruct
}
}
func main() {
buildNewStruct := getStruct("A") //Lets assume "A" here is got as an argument
var strSlice = []string{"Bob", "US"}
buildNewStruct(strSlice) //How to do this operation?
//I am hoping to use buildNewStruct(strSlice) to dynamically call
//either of newA(strSlice) or newB(strSlice) function
}
I have tried looking at this and this the later is not exactly the same as my question.
Since I am new to go, I am not sure if something like this is possible.
you can use the reflect package to set the struct properties to the equivalent index positioned value from an []interface{} slice.
package main
import (
"fmt"
"log"
"reflect"
)
func main() {
var a A
err := decode(&a, []interface{}{"Name", "Place"})
log.Println(err)
log.Println(a)
}
func decode(dst interface{}, values []interface{}) error {
rvptr := reflect.ValueOf(dst)
if rvptr.Kind() != reflect.Ptr {
return fmt.Errorf("value must be ptr")
}
rv := rvptr.Elem()
if rv.NumField() < len(values) {
return fmt.Errorf("too many values")
}
if rv.NumField() > len(values) {
return fmt.Errorf("too few values")
}
rvalues := reflect.ValueOf(values)
for i := range values {
f := rv.FieldByIndex([]int{i})
f.Set(rvalues.Index(i).Elem())
}
return nil
}
type A struct {
Name string
Place string
}
type B struct {
Name string
Place string
Value string
}
prints
$ go run main.go
2019/11/21 17:00:17 <nil>
2019/11/21 17:00:17 {Name Place}
The problem is the return type for the function.
func newA(in []string) interface{} {...}
func newB(in []string) interface{} {...}
func getStruct(name string) func([]string) interface{} {
switch name {
case "A": return newA
case "B": return newB
}
return nil
}
func main() {
buildNewStruct := getStruct("A")
var strSlice = []string{"Bob", "US"}
str:=buildNewStruct(strSlice)
if a, ok:=str.(A); ok {
...
}
}
With this approach, even though you saved some code by calling a unified buildNewStruct(), you have to use type assertions to figure out what is returned from that function, so this may not make a lot of sense. It depends on your exact use case though.
Here is a simple go program that is not working :
package main
import "fmt"
type Vertex struct {
X int
Y int
}
func main() {
v := Vertex{1, 2}
fmt.Println(getProperty(&v, "X"))
}
func getProperty(v *Vertex, property string) (string) {
return v[property]
}
Error:
prog.go:18: invalid operation: v[property] (index of type *Vertex)
What I want is to access the Vertex X property using its name. If I do v.X it works, but v["X"] doesn't.
Can someone tell me how to make this work ?
Most code shouldn't need this sort of dynamic lookup. It's inefficient compared to direct access (the compiler knows the offset of the X field in a Vertex structure, it can compile v.X to a single machine instruction, whereas a dynamic lookup will need some sort of hash table implementation or similar). It's also inhibits static typing: the compiler has no way to check that you're not trying to access unknown fields dynamically, and it can't know what the resulting type should be.
But... the language provides a reflect module for the rare times you need this.
package main
import "fmt"
import "reflect"
type Vertex struct {
X int
Y int
}
func main() {
v := Vertex{1, 2}
fmt.Println(getField(&v, "X"))
}
func getField(v *Vertex, field string) int {
r := reflect.ValueOf(v)
f := reflect.Indirect(r).FieldByName(field)
return int(f.Int())
}
There's no error checking here, so you'll get a panic if you ask for a field that doesn't exist, or the field isn't of type int. Check the documentation for reflect for more details.
You now have the project oleiade/reflections which allows you to get/set fields on struct value or pointers.
It makes using the reflect package less tricky.
s := MyStruct {
FirstField: "first value",
SecondField: 2,
ThirdField: "third value",
}
fieldsToExtract := []string{"FirstField", "ThirdField"}
for _, fieldName := range fieldsToExtract {
value, err := reflections.GetField(s, fieldName)
DoWhatEverWithThatValue(value)
}
// In order to be able to set the structure's values,
// a pointer to it has to be passed to it.
_ := reflections.SetField(&s, "FirstField", "new value")
// If you try to set a field's value using the wrong type,
// an error will be returned
err := reflection.SetField(&s, "FirstField", 123) // err != nil
With getAttr, you can get and set easy.
package main
import (
"fmt"
"reflect"
)
func getAttr(obj interface{}, fieldName string) reflect.Value {
pointToStruct := reflect.ValueOf(obj) // addressable
curStruct := pointToStruct.Elem()
if curStruct.Kind() != reflect.Struct {
panic("not struct")
}
curField := curStruct.FieldByName(fieldName) // type: reflect.Value
if !curField.IsValid() {
panic("not found:" + fieldName)
}
return curField
}
func main() {
type Point struct {
X int
y int // Set prefix to lowercase if you want to protect it.
Z string
}
p := Point{3, 5, "Z"}
pX := getAttr(&p, "X")
// Get test (int)
fmt.Println(pX.Int()) // 3
// Set test
pX.SetInt(30)
fmt.Println(p.X) // 30
// test string
getAttr(&p, "Z").SetString("Z123")
fmt.Println(p.Z) // Z123
py := getAttr(&p, "y")
if py.CanSet() { // The necessary condition for CanSet to return true is that the attribute of the struct must have an uppercase prefix
py.SetInt(50) // It will not execute here because CanSet return false.
}
fmt.Println(p.y) // 5
}
Run it on 👉
Reference
CanSet
A Good example of the reflex: https://stackoverflow.com/a/6396678
You can marshal the struct and unmarshal it back to map[string]interface{}. But, it would convert all the number values to float64 so you would have to convert it to int manually.
type Vertex struct {
X int
Y int
}
func main() {
v := Vertex{1, 2}
fmt.Println(getProperty(&v, "X"))
}
func getProperty(v *Vertex, property string) float64 {
m, _ := json.Marshal(v)
var x map[string]interface{}
_ = json.Unmarshal(m, &x)
return x[property].(float64)
}
I want to offer a different approach that is not using reflection:
package main
import "fmt"
type Vertex struct {
X int
Y int
}
func main() {
v := Vertex{1, 2}
fmt.Println(getProperty(&v, "X"))
}
type Getter func(v *Vertex) int
var VertexAccess = map[string]Getter{
"X": func(v *Vertex) int { return v.X },
"Y": func(v *Vertex) int { return v.Y },
}
func getProperty(v *Vertex, property string) int {
return VertexAccess[property](v)
}
https://go.dev/play/p/2E7LZBWx7yZ
This is an O(1) map lookup and a function call which should perform better than reflection. Obviously, you need some scaffolding code for every type you want to support. On the plus side, you can refactor your code easily; your function getProperty is a potential anti-pattern to https://martinfowler.com/bliki/TellDontAsk.html
What is the way of printing "Foo" here? In this example, what prints is "string".
http://play.golang.org/p/ZnK6PRwEPp
type A struct {
Foo string
}
func (a *A) PrintFoo() {
fmt.Println("Foo value is " + a.Foo)
}
func main() {
a := &A{Foo: "afoo"}
val := reflect.Indirect(reflect.ValueOf(a))
fmt.Println(val.Field(0).Type().Name())
}
You want val.Type().Field(0).Name. The Field method on reflect.Type will return a struct describing that field, which includes the name, among other information.
There is no way to retrieve the field name for a reflect.Value representing a particular field value, since that is a property of the containing struct.
I think the better way to get the fields' name in the struct is
func main() {
a := &A{Foo: "afoo"}
val := reflect.ValueOf(a).Elem()
for i:=0; i<val.NumField();i++{
fmt.Println(val.Type().Field(i).Name)
}
}
There are two tips:
use .Elem() after you reflect.ValueOf(a), because in your case, a is a pointer.
val.Field(i).Type().Name is totally different from val.Type().Field(i).Name. The latter one can get the name of the field in the struct
Hope that it is helpful..
If you want to have a look at more cases, please check my 2mins article
You need to Get the Field of the Type Definition not of the Value.
http://play.golang.org/p/7Bc7MJikbJ
package main
import "fmt"
import "reflect"
type A struct {
Foo string
}
func (a *A) PrintFoo() {
fmt.Println("Foo value is " + a.Foo)
}
func main() {
a := &A{Foo: "afoo"}
val := reflect.Indirect(reflect.ValueOf(a))
fmt.Println(val.Type().Field(0).Name)
}
With the new Names method of the structs package it's even more easier:
package main
import (
"fmt"
"github.com/fatih/structs"
)
type A struct {
Foo string
Bar int
}
func main() {
names := structs.Names(&A{})
fmt.Println(names) // ["Foo", "Bar"]
}
You can also use https://github.com/fatih/structs
// Convert the fields of a struct to a []*Field
fields := s.Fields()
for _, f := range fields {
fmt.Printf("field name: %+v\n", f.Name())
}
package main
import "fmt"
import "reflect"
type A struct {
Foo string
}
func (a *A) PrintFoo() {
fmt.Println("Foo value is " + a.Foo)
}
func main() {
a := &A{Foo: "afoo"}
//long and bored code
t := reflect.TypeOf(*a)
if t.Kind() == reflect.Struct {
for i := 0; i < t.NumField(); i++ {
fmt.Println(t.Field(i).Name)
}
} else {
fmt.Println("not a stuct")
}
//shorthanded call
fmt.Println(reflect.TypeOf(*a).Field(0).Name)//can panic if no field exists
}
You can use this function, which takes the struct as the first parameter, and then its fields. It returns the map type, which is convenient to use
If you use fields from another structure, nothing will happen
If you try to use a different type, it will cause panic
Note that the field has an ordinal number according to the list (starting from 0). All fields in the structure must start with uppercase
func GetStructFieldName(Struct interface{}, StructField ...interface{}) (fields map[int]string) {
fields = make(map[int]string)
s := reflect.ValueOf(Struct).Elem()
for r := range StructField {
f := reflect.ValueOf(StructField[r]).Elem()
for i := 0; i < s.NumField(); i++ {
valueField := s.Field(i)
if valueField.Addr().Interface() == f.Addr().Interface() {
fields[i] = s.Type().Field(i).Name
}
}
}
return fields
}
Full example and playground
package main
import (
"fmt"
"reflect"
)
type Example struct {
Apple bool
Pear int
}
func GetStructFieldName(Struct interface{}, StructField ...interface{}) (fields map[int]string) {
fields = make(map[int]string)
for r := range StructField {
s := reflect.ValueOf(Struct).Elem()
f := reflect.ValueOf(StructField[r]).Elem()
for i := 0; i < s.NumField(); i++ {
valueField := s.Field(i)
if valueField.Addr().Interface() == f.Addr().Interface() {
fields[i] = s.Type().Field(i).Name
}
}
}
return fields
}
func main() {
e := Example{}
names := GetStructFieldName(&e, &e.Apple, &e.Pear)
fmt.Println(names)
fmt.Println(names[0], names[1])
for i := range names {
fmt.Println(names[i])
}
/* Output:
map[0:Apple 1:Pear]
Apple Pear
Apple
Pear
*/
}
Here is a simple go program that is not working :
package main
import "fmt"
type Vertex struct {
X int
Y int
}
func main() {
v := Vertex{1, 2}
fmt.Println(getProperty(&v, "X"))
}
func getProperty(v *Vertex, property string) (string) {
return v[property]
}
Error:
prog.go:18: invalid operation: v[property] (index of type *Vertex)
What I want is to access the Vertex X property using its name. If I do v.X it works, but v["X"] doesn't.
Can someone tell me how to make this work ?
Most code shouldn't need this sort of dynamic lookup. It's inefficient compared to direct access (the compiler knows the offset of the X field in a Vertex structure, it can compile v.X to a single machine instruction, whereas a dynamic lookup will need some sort of hash table implementation or similar). It's also inhibits static typing: the compiler has no way to check that you're not trying to access unknown fields dynamically, and it can't know what the resulting type should be.
But... the language provides a reflect module for the rare times you need this.
package main
import "fmt"
import "reflect"
type Vertex struct {
X int
Y int
}
func main() {
v := Vertex{1, 2}
fmt.Println(getField(&v, "X"))
}
func getField(v *Vertex, field string) int {
r := reflect.ValueOf(v)
f := reflect.Indirect(r).FieldByName(field)
return int(f.Int())
}
There's no error checking here, so you'll get a panic if you ask for a field that doesn't exist, or the field isn't of type int. Check the documentation for reflect for more details.
You now have the project oleiade/reflections which allows you to get/set fields on struct value or pointers.
It makes using the reflect package less tricky.
s := MyStruct {
FirstField: "first value",
SecondField: 2,
ThirdField: "third value",
}
fieldsToExtract := []string{"FirstField", "ThirdField"}
for _, fieldName := range fieldsToExtract {
value, err := reflections.GetField(s, fieldName)
DoWhatEverWithThatValue(value)
}
// In order to be able to set the structure's values,
// a pointer to it has to be passed to it.
_ := reflections.SetField(&s, "FirstField", "new value")
// If you try to set a field's value using the wrong type,
// an error will be returned
err := reflection.SetField(&s, "FirstField", 123) // err != nil
With getAttr, you can get and set easy.
package main
import (
"fmt"
"reflect"
)
func getAttr(obj interface{}, fieldName string) reflect.Value {
pointToStruct := reflect.ValueOf(obj) // addressable
curStruct := pointToStruct.Elem()
if curStruct.Kind() != reflect.Struct {
panic("not struct")
}
curField := curStruct.FieldByName(fieldName) // type: reflect.Value
if !curField.IsValid() {
panic("not found:" + fieldName)
}
return curField
}
func main() {
type Point struct {
X int
y int // Set prefix to lowercase if you want to protect it.
Z string
}
p := Point{3, 5, "Z"}
pX := getAttr(&p, "X")
// Get test (int)
fmt.Println(pX.Int()) // 3
// Set test
pX.SetInt(30)
fmt.Println(p.X) // 30
// test string
getAttr(&p, "Z").SetString("Z123")
fmt.Println(p.Z) // Z123
py := getAttr(&p, "y")
if py.CanSet() { // The necessary condition for CanSet to return true is that the attribute of the struct must have an uppercase prefix
py.SetInt(50) // It will not execute here because CanSet return false.
}
fmt.Println(p.y) // 5
}
Run it on 👉
Reference
CanSet
A Good example of the reflex: https://stackoverflow.com/a/6396678
You can marshal the struct and unmarshal it back to map[string]interface{}. But, it would convert all the number values to float64 so you would have to convert it to int manually.
type Vertex struct {
X int
Y int
}
func main() {
v := Vertex{1, 2}
fmt.Println(getProperty(&v, "X"))
}
func getProperty(v *Vertex, property string) float64 {
m, _ := json.Marshal(v)
var x map[string]interface{}
_ = json.Unmarshal(m, &x)
return x[property].(float64)
}
I want to offer a different approach that is not using reflection:
package main
import "fmt"
type Vertex struct {
X int
Y int
}
func main() {
v := Vertex{1, 2}
fmt.Println(getProperty(&v, "X"))
}
type Getter func(v *Vertex) int
var VertexAccess = map[string]Getter{
"X": func(v *Vertex) int { return v.X },
"Y": func(v *Vertex) int { return v.Y },
}
func getProperty(v *Vertex, property string) int {
return VertexAccess[property](v)
}
https://go.dev/play/p/2E7LZBWx7yZ
This is an O(1) map lookup and a function call which should perform better than reflection. Obviously, you need some scaffolding code for every type you want to support. On the plus side, you can refactor your code easily; your function getProperty is a potential anti-pattern to https://martinfowler.com/bliki/TellDontAsk.html