Look at my code here
package main
import (
"fmt"
)
type iFormatter interface {
SetName(name string)
Format() string
}
type BaseFormatter struct {
name string
}
type Formatter struct {
BaseFormatter
}
func (f Formatter) SetName(name string) {
f.name = name
}
func (f Formatter) Format() string {
return "formatted " + f.name
}
func main() {
var formatters = []iFormatter{Formatter{}}
formatters[0].SetName("KARL")
fmt.Println(formatters[0].Format())
}
I don't understand, why the field "name" is not setted after calling SetName.
Here is the link for playground https://play.golang.org/p/Jkcjv_hFRC.
The SetName() method should be on a pointer, not value. Currently the f is a copy of the formatters[0] and changes to f are not propagated to formatters[0].
The code below should do the trick.
func (f *Formatter) SetName(name string) {
f.name = name
}
...
var formatters = []iFormatter{&Formatter{}}
You don't need to change the Format() method to pointer receiver though in your case it could be better to do it.
See: https://play.golang.org/p/rFmCZesbTB
In your code, changing these two methods like this should make it work as you expect:
func (f *Formatter) SetName(name string) {
f.name = name
}
func (f *Formatter) Format() string {
return "formatted " + f.name
}
and using a pointer as
var formatters = []iFormatter{&Formatter{}}
https://play.golang.org/p/eSX3mXys-a
Basically, using a pointer receiver instead of a value receiver. Using a value receiver works on a copy of the struct instead of the original struct.
Related
In this bizarre example, someone has created a new type which is really just a string:
type CustomType string
const (
Foobar CustomType = "somestring"
)
func SomeFunction() string {
return Foobar
}
However, this code fails to compile:
cannot use Foobar (type CustomType) as type string in return argument
How would you fix SomeFunction so that it is able to return the string value of Foobar ("somestring") ?
Convert the value to a string:
func SomeFunction() string {
return string(Foobar)
}
Better to define a String function for the Customtype - it can make your life easier over time - you have better control over things as and if the structure evolves. If you really need SomeFunction then let it return Foobar.String()
package main
import (
"fmt"
)
type CustomType string
const (
Foobar CustomType = "somestring"
)
func main() {
fmt.Println("Hello, playground", Foobar)
fmt.Printf("%s", Foobar)
fmt.Println("\n\n")
fmt.Println(SomeFunction())
}
func (c CustomType) String() string {
fmt.Println("Executing String() for CustomType!")
return string(c)
}
func SomeFunction() string {
return Foobar.String()
}
https://play.golang.org/p/jMKMcQjQj3
For every type T, there is a corresponding conversion operation T(x)
that converts the value x to type T. A conversion from one type to
another is allowed if both have the same underlying type, or if both
are unnamed pointer types that point to variables of the same
underlying type; these conversions change the type but not the
representation of the value. If x is assignable to T, a conversion
is permitted but is usually redundant. - Taken from The Go
Programming Language - by Alan A. A. Donovan
As per your example here are some of the different examples which will return the value.
package main
import "fmt"
type CustomType string
const (
Foobar CustomType = "somestring"
)
func SomeFunction() CustomType {
return Foobar
}
func SomeOtherFunction() string {
return string(Foobar)
}
func SomeOtherFunction2() CustomType {
return CustomType("somestring") // Here value is a static string.
}
func main() {
fmt.Println(SomeFunction())
fmt.Println(SomeOtherFunction())
fmt.Println(SomeOtherFunction2())
}
It will output:
somestring
somestring
somestring
The Go Playground link
You can convert like this:
var i int = 42
var f float64 = float64(i)
check here
you can return like this:
return string(Foobar)
I have a struct and the instance of that struct:
type Obj struct {
ssid string
code string
mit string
// and other props (23)
}
var ValidObject = Obj {
ssid: "AK93-KADJ9-92J76",
code: "SKO-120O"
mit: "MSLA-923-OKSW"
}
I want to create a slice of structs (Obj) which will contain ValidObject with only some fields changed. I think the best way to explain that would be using pseudo code, so here it is (using spread operator from JS :) ):
var slc = []Obj{
{
...ValidObject,
code: "Other value",
},
{
...ValidObject,
mit: "Other value"
}
}
Create a helper function that takes an Object, changes its code and returns the new Object:
func withCode(obj Obj, code string) Obj {
obj.code = code
return obj
}
Note that withCode takes a non-pointer value, so the Object you pass will not be modified, only the local copy.
And using this your task is:
var slc = []Obj{
withCode(ValidObject, "Other value"),
withCode(ValidObject, "Yet another value"),
}
fmt.Println(slc)
Output (try it on the Go Playground):
[{AK93-KADJ9-92J76 Other value MSLA-923-OKSW}
{AK93-KADJ9-92J76 Yet another value MSLA-923-OKSW}]
This helper withCode could even be a method (not a function).
Note that if you need to have variations of many fields, it would probably be better to add these as methods, so you can chain the calls.
For example:
func (o Obj) withCode(code string) Obj {
o.code = code
return o
}
func (o Obj) withSsid(ssid string) Obj {
o.ssid = ssid
return o
}
func (o Obj) withMit(mit string) Obj {
o.mit = mit
return o
}
And then using it:
var slc = []Obj{
ValidObject.withCode("code2").withSsid("ssid2"),
ValidObject.withMit("mit2").withSsid("ssid3"),
}
fmt.Println(slc)
Output (try it on the Go Playground):
[{ssid2 code2 MSLA-923-OKSW} {ssid3 SKO-120O mit2}]
Create a slice of struct var objCollector = []obj{} globally and read data into the defined struct and append the object into slice of struct that we created.
type Obj struct {
ssid string
code string
mit string
}
var objCollector = []obj{}
func main() {
var ValidObject = Obj{
ssid: "AK93-KADJ9-92J76",
code: "SKO-120O",
mit: "MSLA-923-OKSW",
}
append(objectCollector, ValidObject)
}
Foreign application API gives me a list of names in JSON format. I need modify all of those.
But I do not like to write some loop for it (especially after Python using with reflection and stuff)
Is there any method to write something like this in Go?
type MyIncredibleType struct {
Name ModifyName // ModifyName is not a type!
}
func ModifyName(input string) string {
return input + ".com"
}
The expected behavior of this is:
a := MyIncredibleType{Name: "Abracadabra"}
print(a.Name) // Abracadabra.com
This seems pretty straight forward to me, assuming I understand your question correctly:
// ModifyName func
func ModifyName(input string) string {
return fmt.Sprintf("%v.com", input)
}
If you wish to achieve this within the type itself, without modifying (mutating) the internal state:
type MyType sturct {
name string // unexported
}
// accessor func to return name
func (t MyType) Name() string {
return t.name
}
// accessor func to return modified name
func (t MyType) ModifiedName() string {
return fmt.Sprintf("%v.com", t.name)
}
If you want to modify the internal state:
type MyType struct {
name string
}
// mutator func (note the pointer for pass by reference)
func (t *MyType) ModifyName(input string) {
t.name = fmt.Sprintf("%v.com", input)
}
// accessor (note no pointer for pass by value)
func (t MyType) Name() string {
return t.name
}
This is is not possible in GO. That's not how struct works in Go.
type MyIncredibleType struct {
Name ModifyName `json:"name"` // ModifyName is not a type!
}
you can only define Built-in types for your fields of struct or you can define Composite Literal types.
Composite literals construct values for structs, arrays, slices, and
maps and create a new value each time they are evaluated. They consist
of the type of the literal followed by a brace-bound list of elements.
Each element may optionally be preceded by a corresponding key.
Try to create a method receiver of struct which you are using to parse json coming from the api to modify the name. That will let you achieve something similar to what you want.
package main
import (
"fmt"
)
type MyIncredibleType struct {
Name string `json:"name"` // ModifyName is not a type!
}
func(myIncredibleType *MyIncredibleType) ModifyName() string {
return myIncredibleType.Name+".com"
}
func main() {
a := MyIncredibleType{Name: "Abracadabra"}
name := a.ModifyName()
fmt.Printf("%s",name)
}
Playground Example
Or you can pass an interface which will wrap any struct value with name field and then use Type assertion to get the underlying value to modify the same and return the result:
package main
import (
"fmt"
)
type MyIncredibleType struct {
Name string `json:"name"` // ModifyName is not a type!
}
func ModifyName(input interface{}) string{
return input.(interface{}).(string)+".com"
}
func main() {
a := MyIncredibleType{Name: "Abracadabra"}
name := ModifyName(a.Name)
fmt.Printf("%s",name)
}
Working code on Go Playground
For more information also go through Golang method Declarations on how to create receivers.
package main
import (
"fmt"
)
type animal interface {
speak()
}
type dog struct {
name, sound string
}
type cat struct {
name, sound string
}
func (d dog) speak() {
fmt.Println(d.name, " goes ", d.sound)
}
func (c cat) speak() {
fmt.Println(c.name, " goes ", c.sound)
}
func animal_speak(a animal) {
fmt.Println(a.speak())
}
func main() {
dogo := dog{"scooby", "woof"}
cato := cat{"garfield", "meow"}
animal_speak(dogo)
animal_speak(cato)
}
When I call the animal interface it gives me the following error
./interface.go:28:21: a.speak() used as value
What am I doing wrong?
Link to playground
The interface is not used as a value. You're using a function call that returns nothing as a value.
speak() returns nothing... so what do you expect it to print?
Since you are printing the output of speak method, your speak method needs to return a string or an object whose string representation would print a string you would like to see. Here's your program modified https://play.golang.org/p/VDsp0cjXBd- to return a string.
This answer is based on all above answers,
Modified below function
Before
func animal_speak(a animal) {
fmt.Println(a.speak())
}
After
func animal_speak(a animal) {
a.speak()
}
Playgorund Link
func (f *FlagSet) IntVar(p *int, name string, value int, usage string) {
f.Var(newIntValue(value, p), name, usage)
}
func (f *FlagSet) Var(value Value, name string, usage string) {
flag := &Flag{name, usage, value, value.String()}
// ...
}
func newIntValue(val int, p *int) *intValue {
*p = val
return (*intValue)(p)
}
type intValue int
type Value interface {
String() string
Set(string) error
}
I read the flag.Int source code, and found:
Standard lib flag.intValue does not implements String and Set method, I doesn't found them, how var value Value = &intValue works?
(Sorry, my native language is not English.)