I'm working on unit tests on a Go project, and I'm new to Go. So to start I wanted to test something easy. And I started with this function:
func (this *Service) InList(idPerson string, personsId []string) bool {
for _, personsId := range personsId {
if id == idPerson {
return true
}
}
return false
}
Service is a struct defined on top of the class.
This is the test I wrote:
func TestValidatePersonID(t *testing.T) {
personID := "12345"
personIDs := []string{"12345", "123456t", "1234567a"}
ok := *Service.InList(personID, personIDs)
if !ok {
t.Errorf("Id %v not found", personID)
}
}
If i try to Call Service without * I get the error:
invalid method expresion (needs pointer reciever)
If i try to call the function (*Service).inList, it says I'm missing an argument. I'm new to Go if anyone could point to me what I'm doing wrong and how Could I get a pointer receiver of that Service in my test?. I would appreciatte it.
The correct syntax for the method expression is:
ok := (*Service).InList(nil, personID, personIDs)
This snippet adds nil as the receiver argument and uses parentheses to specify the type correctly.
The approached used in the question is not idiomatic. Either call a method on a value
s := Service{}
ok := s.InList(personID, personIDs)
or convert the method to a function.
You have to call a method on an instance of its receiver type. So, for a method defined on *Service, you must call it on an instance of *Service:
var foo *Service
foo = &Service{}
foo.InList(personID, personIDs)
However, in your case, there's no reason for this to be a method; it doesn't seem to have anything at all to do with its receiver (it never references it), so it could just be a regular function. Also note that it's unidiomatic to name the receiver this in Go.
I also highly recommend at least taking the Go tour, which covers writing methods in detail, with interactive examples.
If you do not reference the receiver object, then you should not have one, keep your code as simple as possible.
There are three ways of writing a method or function, with each its own purpose.
without receiver, when no receiver is referenced in the function ( we call this a function )
a value receiver, the receiver is referenced, but not changed in the method ( we call this a method )
a pointer receiver, something in the receiver will be changed in the method
Related
I just started learning Go a few days ago.Today, we were debugging a piece of code for a while when we found something that seem counterintuitive of Go to do.
First we defined an interface and a data structure that implements it.
type Executer interface {
Execute()
}
type whatever struct {
name string
}
func (this *whatever) Execute() {
log.Println(this.name)
}
Now consider that I have a nil pointer to whatever and I try to call the method Execute. In other object-oriented languages I have used so far, this would call a null pointer error at the point of calling the method (i.e. w.Execute()) since the object pointer is null. Interestingly, in Go, the method is invoked, the null pointer error occurs at the Execute method when I try to dereference this.name. Why not at the point of calling the method?
func main() {
var w *whatever
w.Execute()
}
So, what I'm seeking to understand now is how is this possible? Does this mean that Go only does early method binding at compile time and at runtime there is no binding of the method with a specific object?
The receiver is just an "ordinary" argument to the function. Ordinary parameters may be of pointer types. When then are, you are allowed to pass nil as the argument, which is perfectly valid. All you need to keep in mind is not to dereference nil pointer arguments. The same applies to the special receiver parameter too. If it's a pointer, it may be nil, you just must not dereference it.
Spec: Method declarations:
The receiver is specified via an extra parameter section preceding the method name.
... The method is said to be bound to its receiver base type and the method name is visible only within selectors for type T or *T.
Allowing nil receiver values is not just something not forbidden, it has practical uses. For an example, see Test for nil values in nested stucts.
In Java you can call static methods on null objects too. It's true you can't do the same in Go, because Go does not have modifiers like static, public, private etc. In Go there are only exported and non-exported methods (implied by the first latter of their name).
But Go offers something similar too: Method expressions and Method values. If you have a method m with T receiver type, the expression T.m will be a function value whose signature contains the parameters and result types of m "prefixed" with the receiver type.
For example:
type Foo int
func (f Foo) Bar(s string) string { return fmt.Sprint(s, f) }
func main() {
fooBar := Foo.Bar // A function of type: func(Foo, string) string
res := fooBar(1, "Go")
fmt.Println(res)
}
Foo.Bar will be a function with type func (Foo, string) string, and you can call it like any other ordinary function; and you also have to pass the receiver as the first argument. The above app outputs (try it on the Go Playground):
Go1
Going a little "forward", we are not required to store Foo.Bar in a variable, we can directly call Foo.Bar:
fmt.Println(Foo.Bar(1, "Go"))
Which outputs the same (try it on the Go Playground). Now this almost looks like a static method call in Java.
And as the "final" step, when we use the above expression on a value of Foo itself (instead of the type identifier), we arrive at the method values, which saves the receiver and so the type of a method value does not include the receiver, its signature will be that of the method, and we can call it without having to pass a receiver:
var f Foo = Foo(1)
bar := f.Bar
fmt.Println(bar("Go"))
This again will output the same, try it on the Go Playground.
See related questions:
Pass method argument to function
golang function alias on method receiver
I am passing a pointer to a string, to a method which takes an interface (I have multiple versions of the method, with different receivers, so I am trying to work with empty interfaces, so that I don't end up with a ton of boilerplate madness. Essentially, I want to populate the string with the first value in the slice. I am able to see the value get populated inside the function, but then for some reason, in my application which calls it, tha value doesn't change. I suspect this is some kind of pointer arithmetic problem, but could really use some help!
I have the following interface :
type HeadInterface interface{
Head(interface{})
}
And then I have the following functions :
func Head(slice HeadInterface, result interface{}){
slice.Head(result)
}
func (slice StringSlice) Head(result interface{}){
result = reflect.ValueOf(slice[0])
fmt.Println(result)
}
and... here is my call to the function from an application which calls the mehtod...
func main(){
test := x.StringSlice{"Phil", "Jessica", "Andrea"}
// empty result string for population within the function
var result string = ""
// Calling the function (it is a call to 'x.Head' because I lazily just called th import 'x')
x.Head(test, &result)
// I would have thought I would have gotten "Phil" here, but instead, it is still empty, despite the Println in the function, calling it "phil.
fmt.Println(result)
}
*NOTE : I am aware that getting the first element doesn't need to be this complicated, and could be slice[0] as a straight assertion, but this is more of an exercise in reusable code, and also in trying to get a grasp of pointers, so please don't point out that solution - I would get much more use out of a solution to my actual problem here * :)
As you said in your NOTE, I'm pretty sure this doesn't have to be this complicated, but to make it work in your context:
package main
import (
"fmt"
"reflect"
)
type HeadInterface interface {
Head(interface{})
}
func Head(slice HeadInterface, result interface{}) {
slice.Head(result)
}
type StringSlice []string
func (slice StringSlice) Head(result interface{}) {
switch result := result.(type) {
case *string:
*result = reflect.ValueOf(slice[0]).String()
fmt.Println("inside Head:", *result)
default:
panic("can't handle this type!")
}
}
func main() {
test := StringSlice{"Phil", "Jessica", "Andrea"}
// empty result string for population within the function
var result string = ""
// Calling the function (it is a call to 'x.Head' because I lazily just called th import 'x')
Head(test, &result)
// I would have thought I would have gotten "Phil" here, but instead, it is still empty, despite the Println in the function, calling it "phil.
fmt.Println("outside:", result)
}
The hard part about working with interface{} is that it's hard to be specific about a type's behavior given that interface{} is the most un-specific type. To modify a variable that you pass as a pointer to a function, you have to use the asterisk (dereference) (for example *result) on the variable in order to change the value it points to, not the pointer itself. But to use the asterisk, you have to know it's actually a pointer (something interface{} doesn't tell you) so that's why I used the type switch to be sure it's a pointer to a string.
ERROR: type CustomStruct is not an expression.
type CustomStruct struct {
}
func getTypeName(t interface{}) string {
rt := reflect.TypeOf(t).Elem()
return rt.Name()
}
getTypeName(CustomStruct)
How can I pass struct type to function without type instance?
This will work
getTypeName((*CustomStruct)(nil))
But I wonder if there is more simple version..
You can't. You can only pass a value, and CustomStruct is not a value but a type. Using a type identifier is a compile-time error.
Usually when a "type" is to be passed, you pass a reflect.Type value which describes the type. This is what you "create" inside your getTypeName(), but then the getTypeName() will have little left to do:
func getTypeName(t reflect.Type) string {
return t.Name()
}
// Calling it:
getTypeName(reflect.TypeOf(CustomStruct{}))
(Also don't forget that this returns an empty string for anonymous types such as []int.)
Another way is to pass a "typed" nil pointer value as you did, but again, you can just as well use a typed nil value to create the reflect.Type too, without creating a value of the type in question, like this:
t := reflect.TypeOf((*CustomStruct)(nil)).Elem()
fmt.Println(t.Name()) // Prints CustomStruct
Lets resurrect this!
The generics proposal for Go got approved, and that's coming, eventually. When this question was first asked, this probably made more sense as a question, but for anyone looking to implement a generics pattern now, I think I've got an alright API for it.
For now, you can't interact with abstract types, but you can interact with methods on the abstract type, and reflect allows you to examine function signatures. For a method, the 0th is the receiver.
type Example struct {int}
type Generic struct{reflect.Type}
func (p Example) Type() {}
func Reflect(generic interface{}) Generic {
real := reflect.TypeOf(generic)
if real.Kind() != reflect.Func || real.NumIn() < 1 {
panic("reflect.Type.In(n) panics if not a func and if n out of bounds")
}
return Generic{real.In(0)}
}
func (g Generic) Make() interface{} {
return reflect.Zero(g.Type).Interface()
}
func main() {
tOfp := Reflect(Example.Type)
fmt.Printf("Name of the type: %v\n", tOfp.Name())
fmt.Printf("Real (initial)value: %v\n", tOfp.Make())
}
Some quick notes:
The structure of "Example" doesn't matter, rather only that it has a method with a non-pointer receiver.
The definition of a type called "Generic" as a struct is to accomplish what I believed OP's actual intent to be.
The above definition of "Generic" is a struct instead of an interface so that it can have its own method set. Defining "Generic" as an interface, and using a methodset specific to each operand-type used with it would make tons of sense.
If you weren't aware, actual generics are coming in Go 1.18. My example above has no linter or compile protection, and will panic at runtime if used incorrectly. It does work, and will let you reason over abstract types while you wait for a native implementation.
Happy Coding!
From Go version 1.18 a new feature Generics has been introduced. In most of the case instead of passing types to function, we can use generics. Then we will also get compile time error instead of runtime error and it's more efficient than reflect also.
Example Code
func HttpGet[T](url, body) T {
var resp T
return T
}
resp := HttpGet[ResponseType]("dummy.example", nil)
I am following a Go tutorial and am stuck as I cant understand a particular method signature:
func (p *Page) save() error {
filename := p.Title + ".txt"
return ioutil.WriteFile(filename, p.Body, 0600)
}
The docs explain this as follows:
This method's signature reads: "This is a method named save that takes as its receiver p, a pointer to Page . It takes no parameters, and returns a value of type error."
I cant understand what the receiver is. I would read this as it being a parameter but then I would expect a parameter to be in save().
The receiver is just a special case of a parameter. Go provides syntactic sugar to attach methods to types by declaring the first parameter as a receiver.
For instance:
func (p *Page) save() error
reads "attach a method called save that returns an error to the type *Page", as opposed to declaring:
func save(p *Page) error
that would read "declare a function called save that takes one parameter of type *Page and returns an error"
As proof that it's only syntactic sugar you can try out the following code:
p := new(Page)
p.save()
(*Page).save(p)
Both last lines represent exactly the same method call.
Also, read this answer.
The receiver is the object on what you declare your method.
When want to add a method to an object, you use this syntax.
ex: http://play.golang.org/p/5n-N_Ov6Xz
Suppose I have the following code:
package main
import "fmt"
type Car struct{
year int
make string
}
func (c *Car)String() string{
return fmt.Sprintf("{make:%s, year:%d}", c.make, c.year)
}
func main() {
myCar := Car{year:1996, make:"Toyota"}
fmt.Println(myCar)
}
When I call fmt.Println(myCar) and the object in question is a pointer, my String() method gets called properly. If, however the object is a value, my output is formatted using the default formatting built into Go and my code to format the said object is not called.
The interesting thing is in either case if I call myCar.String() manually it works properly whether my object is either a pointer or value.
How can I get my object formatted the way I want no matter if the object is value-based or pointer-based when used with Println?
I don't want to use a value method for String because then that means every time it's invoked the object is copied which seams unreasonable. And I don't want to have to always manually called .String() either because I'm trying to let the duck-typing system do it's work.
When calling fmt.Println, myCar is implicitly converted to a value of type interface{} as you can see from the function signature. The code from the fmt package then does a type switch to figure out how to print this value, looking something like this:
switch v := v.(type) {
case string:
os.Stdout.WriteString(v)
case fmt.Stringer:
os.Stdout.WriteString(v.String())
// ...
}
However, the fmt.Stringer case fails because Car doesn't implement String (as it is defined on *Car). Calling String manually works because the compiler sees that String needs a *Car and thus automatically converts myCar.String() to (&myCar).String(). For anything regarding interfaces, you have to do it manually. So you either have to implement String on Car or always pass a pointer to fmt.Println:
fmt.Println(&myCar)
Methods
Pointers vs. Values
The rule about pointers vs. values for receivers is that value methods
can be invoked on pointers and values, but pointer methods can only be
invoked on pointers. This is because pointer methods can modify the
receiver; invoking them on a copy of the value would cause those
modifications to be discarded.
Therefore, for your String method to work when invoked on both pointers and values, use a value receiver. For example,
package main
import "fmt"
type Car struct {
year int
make string
}
func (c Car) String() string {
return fmt.Sprintf("{make:%s, year:%d}", c.make, c.year)
}
func main() {
myCar := Car{year: 1996, make: "Toyota"}
fmt.Println(myCar)
fmt.Println(&myCar)
}
Output:
{make:Toyota, year:1996}
{make:Toyota, year:1996}
Define your fmt.Stringer on a pointer receiver:
package main
import "fmt"
type Car struct {
year int
make string
}
func (c *Car) String() string {
return fmt.Sprintf("{maker:%s, produced:%d}", c.make, c.year)
}
func main() {
myCar := Car{year: 1996, make: "Toyota"}
myOtherCar := &Car{year: 2013, make: "Honda"}
fmt.Println(&myCar)
fmt.Println(myOtherCar)
}
Playground
Output:
{maker:Toyota, produced:1996}
{maker:Honda, produced:2013}
Then, always pass a pointer to instances of Car to fmt.Println. This way a potentially expensive value copy is avoided under your control.
The OP further asked:
OP: [when a value receiver is used] "Does this basically mean that if I have a large struct, then every time it goes through Println it will be copied?"
The following experiment is evidence that the answer is "yes" (when a value receiver is used). Note that the String() method increments the year in this experiment, and check how this affects the printed output.
type Car struct {
year int
make string
}
func (c Car) String() string {
s := fmt.Sprintf("{ptr:%p, make:%s, year:%d}", c, c.make, c.year)
// increment the year to prove: is c a copy or a reference?
c.year += 1
return s
}
func main() {
myCar := Car{year: 1996, make: "Toyota"}
fmt.Println(&myCar)
fmt.Println(&myCar)
fmt.Println(myCar)
fmt.Println(myCar)
}
With a value receiver (c Car), the following printed output shows that Go makes value copies of the Car struct, because the year increment is not reflected in subsequent calls to Println:
{ptr:%!p(main.Car={1996 Toyota}), make:Toyota, year:1996}
{ptr:%!p(main.Car={1996 Toyota}), make:Toyota, year:1996}
{ptr:%!p(main.Car={1996 Toyota}), make:Toyota, year:1996}
{ptr:%!p(main.Car={1996 Toyota}), make:Toyota, year:1996}
Changing the receiver to a pointer (c *Car) but changing nothing else, the printed output becomes:
{ptr:0xc420094020, make:Toyota, year:1996}
{ptr:0xc420094020, make:Toyota, year:1997}
{1998 Toyota}
{1998 Toyota}
Even when a pointer is provided as argument in a call to Println, i.e. fmt.Println(&myCar), Go still makes a value copy of the Car struct when a value receiver is used. The OP wants to avoid value copies being made, and my conclusion is that only pointer receivers satisfy that requirement.
It's only related to implementation of fmt instead of Go however.
String() with pointer receiver would be invoked by https://github.com/davecgh/go-spew since spew print things in this way:
v = reflect.ValueOf(arg)
...
switch iface := v.Interface().(type) {
case fmt.Stringer:
defer catchPanic(w, v)
if cs.ContinueOnMethod {
w.Write(openParenBytes)
w.Write([]byte(iface.String()))
w.Write(closeParenBytes)
w.Write(spaceBytes)
return false
}
w.Write([]byte(iface.String()))
return true
}
Generally speaking, it's best to avoid assigning values to variables via static initializers, i.e.
f := Foo{bar:1,baz:"2"}
This is because it can create exactly the complaint you're talking about, if you forget to pass foo as a pointer via &foo or you decide to use value receivers you end up making a lot of clones of your values.
Instead, try to assign pointers to static initializers by default, i.e.
f := &Foo{bar:1,baz:"2"}
This way f will always be a pointer and the only time you'll get a value copy is if you explicitly use value receivers.
(There are of course times when you want to store the value from a static initializer, but those should be edge cases)