golang interface "used as value" error - go

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

Related

Golang inheritance - Cannot use (type func(d Dog)) as the type func(animal Animal)

I was tring to write a method callGetName which can take both getCatName and getDogName method as its parameter while my IDE tells me:
Cannot use 'getDogName' (type func(d Dog)) as the type func(animal Animal)
package main
type Animal struct {
Name string
}
type Cat struct {
Animal
}
type Dog struct {
Animal
}
func getCatById(c Cat) {}
func validateDogNames(d Dog) {}
func invokeFunc(f func(animal Animal)) {}
func main() {
invokeFunc(getCatById)
invokeFunc(validateDogNames)
}
I tried to analyze the reason, maybe it's because golang supports multiple inheritance?
Please let me know if I was doing something stupid or is there any better way to achieve this?
========
A little more about why I'm trying this: in go-kit framework, I have to write makeEndpoint functions for every single service method defined. And I used reflect to adopt a generic makeEndpoints like below:
func NewProductEndpoints() ProductEndpoints {
ps := service.NewProductService()
return ProductEndpoints{
GetProductById: makeEndpoint(ps, util.GetFunctionName(ps.GetProductById)),
CreateProduct: makeEndpoint(ps, util.GetFunctionName(ps.CreateProduct)),
}
}
func makeEndpoint(s service.ProductService, funcName string) kitEndpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
req := request.(domain.ProductDTO)
currFunc := reflect.ValueOf(s).MethodByName(funcName)
args := []reflect.Value{reflect.ValueOf(req)}
res := currFunc.Call(args)[0]
return res, nil
}
}
wondering if there's a better way to achieve. Thanks in advance.
So you're thinking in a fairly OOP fashion, Go does not have inheritance (to clarify it has struct embedding which is what you are doing in your first example). We tend to favour composition to solve problems.
One way you could look at solving your problem is like the below.
package main
import (
"fmt"
)
type Namer interface {
Name() string
}
type Cat struct {
name string
}
func (c Cat) Name() string {
return c.name
}
type Dog struct {
name string
}
func (d Dog) Name() string {
return d.name
}
func PetName(n Namer) {
fmt.Println(n.Name())
}
func main() {
PetName(Dog{name: "Fido"})
PetName(Cat{name: "Mittens"})
}
Names can be improved, but it should act as a basic example of an approach that could be taken.
Edit: Example based on comment left below
package main
import (
"fmt"
)
type Invoker interface {
Invoke()
}
type Dog struct{}
func (Dog) Bark() {
fmt.Println("Woof")
}
func (d Dog) Invoke() {
d.Bark()
}
type Cat struct{}
func (Cat) Meow() {
fmt.Println("Meow")
}
func (c Cat) Invoke() {
c.Meow()
}
func CallFunc(i Invoker) {
i.Invoke()
}
func main() {
CallFunc(Cat{})
CallFunc(Dog{})
}

Is there a more idiomatic approach to creating variables of specific types based on input?

In this playground link I have created a contrived version of my code where I am creating a variable of type X based on an input string. The variable will be one of a handful of types and implement an interface.
The code currently compiles and provides the correct result, however it strikes me as quite verbose and I'm trying to find if there is a shorthand approach to the result I'm achieving. The example has 3 types (dog, cat & bird) that implement the interface (animal), however my actual code will have up to 40 types in this switch statement.
The reason I am using this code is when retrieving results form a DBMS, I'm trying to use a generic load method that, when combined with sqlx, loads the database table into the correct struct based on the input string. I have entire control over the application and can change the input string to another type if required.
Code from playground link:
package main
import (
"fmt"
)
type animal interface {
call() string
}
type dog struct {
}
func (d *dog) call() string {
return "Woof!"
}
type cat struct {
}
func (c *cat) call() string {
return "Meow!"
}
type bird struct {
}
func (c *bird) call() string {
return "Chirp!"
}
func main() {
var animal animal
animalType := "dog"
switch animalType{
case "dog":
animal = new(dog)
case "cat":
animal = new(cat)
case "bird":
animal = new(bird)
You can create a hashmap from "string" to "function that returns animal" but setting that up would be more verbose than the switch statement.
Something like this (not tested)
type AnimalCtor func() animal
var animalMap map[string]AnimalCtor
.....
func init() {
animalMap["dog"] = func() animal { return &dog{} }
animalMap["cat"] = func() animal { return &cat{} }
animalMap["bird"] = func() animal { return &bird{} }
.....
}
func createAnimalFromString(input string) animal {
ctor, ok := animalMap[input]
if ok {
return ctor()
} else {
return nil
}
}
But it's a lot more verbose than the switch statement and obscures what should otherwise be explicit and clear.

How do I convert an interface{} value to a statically typed value using a function in golang?

In standard library, I can do JSON conversion to a typed object using pointer. The question now is, how do I create a similar method like json.Marshal to convert an v interface{} to typed object? Do I need to use reflect in doing this?
Please see below code snippets, and I am looking for somebody who could fill in the TODO in the home package. Thank you.
package main
import (
"encoding/json"
"fmt"
"./home"
)
type Dog struct {
Name string
FavoriteGame string
}
func (dog Dog) Greet() {
dog.Bark()
}
func (dog Dog) Bark() {
if len(dog.Name) == 0 {
panic("This dog has no name!")
}
fmt.Printf("%s < Wo! Wo! %s!\n", dog.Name, dog.FavoriteGame)
}
type Cat struct {
Name string
FavoriteMeat string
}
func (cat Cat) Greet() {
cat.Purr()
}
func (cat Cat) Purr() {
if len(cat.Name) == 0 {
panic("This cat has no name!")
}
fmt.Printf("%s < purrrrrrr... %s...\n", cat.Name, cat.FavoriteMeat)
}
func main() {
// JSON decoder works here
j := []byte(`{"Name": "Jack", "FavoriteGame": "Swim"}`)
var jack Dog
json.Unmarshal(j, &jack)
jack.Bark()
// Similarly, how do I implement `home` to make the below work?
dogHome := home.Home{Dog{Name: "Bullet", FavoriteGame: "Catch The Ball"}}
var bullet Dog
dogHome.GetPet(&bullet)
bullet.Bark()
catHome := home.Home{Cat{Name: "Ball", FavoriteMeat: "Tuna"}}
var ball Cat
catHome.GetPet(&ball)
ball.Purr()
}
The other package:
package home
type Pet interface {
Greet()
}
type Home struct {
Pet Pet
}
func (h Home) GetPet(v interface{}) {
// TODO: What should I do here?
v = h.Pet
}
Use the reflect package:
func (h Home) GetPet(v interface{}) {
reflect.ValueOf(v).Elem().Set(reflect.ValueOf(h.Pet))
}
The expression reflect.ValueOf(v).Elem() is the reflect value for what the argument points to. The Set method sets that value.
Run it on the playground
A better approach is to use type assertions directly in the application:
dogHome := Home{Dog{Name: "Bullet", FavoriteGame: "Catch The Ball"}}
bullet := dogHome.Pet.(Dog)
bullet.Bark()
catHome := Home{Cat{Name: "Ball", FavoriteMeat: "Tuna"}}
ball := catHome.Pet.(Cat)
ball.Purr()
Run it on the playground

In Go can I return a struct that meets an interface without access to that interface?

I think the best way to explain this is by example, so here it is:
package main
import (
"fmt"
)
// Greeter greets with a Greeting.
type Greeter interface {
Greet() Greeting
}
// A Greeting has a string representation.
type Greeting interface {
String() string
}
type Hello struct {}
// Hello greets by returning itself...
func (h *Hello) Greet() *Hello {
return h
}
// ...because Hello also has a string representation.
func (h *Hello) String() string {
return "Hello"
}
// But Go says Hello doesn't implement Greeter.
func main() {
var g interface{} = &Hello{}
g, ok := g.(Greeter)
fmt.Println(ok)
}
This prints false. You can run and play with it: https://play.golang.org/p/A_2k_ku_Q2
In my real case the struct Hello and the interfaces for Greeter and Greeting are in different packages that do not import each other and I wanted to keep it that way. I'm perhaps missing some understanding of interfaces in Go but after reading so much about it I still can't put my finger on it. Would you guys have any pointers for me? Maybe another approach for the problem? Thanks!
As stated in the comments, problem here is once your interface has this signature:
type Greeter interface {
Greet() Greeting
}
The any valid implementation must use exactly Greeting as the return type.
But, as the documentation shows, you don't need to give the interface a name:
https://golang.org/ref/spec#Interface_types
In order to be able to implement what you need, you might declare the interface directly in the return value, without giving it a name.
// Greeter greets with anything that has a String() method
type Greeter interface {
Greet() interface{ String() string }
}
Then your Greet() function for Hello can do this:
// Hello greets by returning itself...
func (h *Hello) Greet() interface{ String() string } {
return h
}
Find here a modified playground showing the working example:
https://play.golang.org/p/HteA_9jFd4

golang: how is "func() interface {}" and "func() *MyStruct" incompatible types?

Suppose I have code, where a function accepts another one as an argument:
type Person struct {
Name string
}
func personBuilder() * Person {
return &Person{Name: "John"}
}
func printRetrievedItem(callback func() interface {}){
fmt.Print(callback());
}
func doStuff(){
printRetrievedItem(personBuilder);
}
This results in error cannot use personBuilder (type func() *Person) as type func() interface {} in function argument. If I change personBuilder return type to interface{}, it works, but in real project I'm working on I want to have a concrete type for clear design and TDD purposes.
Does Go support such method signature generalization? What are the workarounds, if you could not change the personBuilder part (e.g. you have a lot parameterless functions that return different type of struct, and you want to build a consumer function that accepts any of those builders as argument)?
One workaround is to define an inline function that calls personBuilder.
printRetrievedItem(func() interface{} {return personBuilder()});
Playground
You can create an interface with a method that returns an interface{}:
type Thinger interface {
Thing() interface{}
}
func (p *Person) Thing() interface{} {
return p
}
func printRetrievedItem(t Thinger){
fmt.Print(t.Thing());
}
func doStuff(){
printRetrievedItem(personBuilder);
}
This is just an example, please use a better name!
To answer your question, fun() A is not a func() interface{}, for the same reason that []A is not an []interface{}. It's explained very well in the go wiki.
Either do a wrapper like #GrzegorzŻur suggested or define your own interface and make your xxxxBuilder return it:
type Namer interface {
Name() string
}
type Person struct {
name string
}
func (p *Person) Name() string {
return p.name
}
func personBuilder() Namer {
return &Person{name: "John"}
}
func printRetrievedItem(callback func() Namer) {
fmt.Printf("%T: %v", callback(), callback().Name())
}
You can use pkg reflect for this. (Note however that the solution of #OneOfOne is more idiomatic).
package main
import (
"fmt"
"reflect"
)
type Person struct {
Name string
}
func personBuilder() *Person {
return &Person{Name: "John"}
}
func printRetrievedItem(callback interface{}) {
vals := reflect.ValueOf(callback).Call([]reflect.Value{})
fmt.Println(vals[0].Interface())
}
func main() {
printRetrievedItem(personBuilder) // &{John}
printRetrievedItem(func() string { return "hello" }) // hello
}
Here's an example in the playground.

Resources