Have trouble understanding a piece of golang code - methods

package main
type Writeable interface {
OnWrite() interface{}
}
type Result struct {
Message string
}
func (r *Result) OnWrite() interface{} {
return r.Message
}
// what does this line mean? what is the purpose?
var _ Writeable = (*Result)(nil)
func main() {
}
The comments in the code snippet expressed my confusion.
As I understood, the line with comment notifies the compiler to check whether a struct has implemented the interface, but I am not sure very much. Could someone help explaining the purpose?

As you say it's a way to verify that Result implements Writeable. From the GO FAQ:
You can ask the compiler to check that the type T implements the
interface I by attempting an assignment:
type T struct{}
var _ I = T{} // Verify that T implements I.
The blank identifier _ stands for the variable name which is not needed here (and thus prevents a "declared but not used" error).
(*Result)(nil) creates an uninitialized pointer to a value of type Result by converting nil to *Result. This avoids allocation of memory for an empty struct as you'd get with new(Result) or &Result{}.

Related

Get method receiver with reflect [duplicate]

Is there a way in Go, to get the receiver object from a method value?
For example, is there any such MagicFunc that would make the following program output the string my info from the underlying Foo instance.
package main
import "fmt"
type Foo struct {
A string
}
func (foo *Foo) Bar() string {
return "bar"
}
func MyFunc(val interface{}) {
i := MagicFunc(val)
f := i.(Foo)
fmt.Println(f.A)
}
func main() {
f := Foo{A: "my info"}
MyFunc(f.Bar)
}
No, it is not possible to get the method's receiver instance.
The most you can get is the receiver's type if you use a method expression instead of method value but that won't help you get the my info string.
I wanted to deep-dive into this a bit and soon found this document: https://golang.org/s/go11func
As describe there, when MyFunc is entered val doesn't contain a reference to f.Bar but rather to a special function with the signature func() string. That function knows that it can retrieve the orignal f pointer by checking the well-known R0 register (in the example. On amd64 it appears to be dx, but that's an implementation detail obviously).
Thus there's no way to do this without using implementation specific assembly code, which would be very fragile.

How to pass type to function argument in Go

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)

Restore type information after passing through function as "interface {}"?

I'm running into a slight architectural problem with Golang right now that's causing me to copy/paste a bit more code than I'd prefer. I feel like there must be a solution, so please let me know if this is perhaps possible:
When I pass things through an interface {}-typed function parameter, I start getting errors such as "expected struct or slice", etc. ... even though what I passed was previously a struct or a slice. I realize that I could manually convert these to another type after receiving them in that function, but then that become tedious in instances such as this:
local interface type *interface {} can only be decoded from remote
interface type; received concrete type
... In this case, the receiving function seems like it'd need to be hard-coded to convert all interface {} items back to their respective original types in order to work properly, because the receiving function needs to know the exact type in order to process the item correctly.
Is there a way to dynamically re-type Golang interface {} typed variables back to their original type? Something like this, How to I convert reflect.New's return value back to the original type ... maybe?
EDIT: To clarify, basically, I'm passing &out to a function and it needs to be its original type by the time it reaches another inner function call.
Example code:
// NOTE: This is sort of pseudo-Golang code, not meant to be compiled or taken too seriously.
func PrepareTwoDifferentThings(keyA string, keyB string) {
var somethingA TypeA;
var somethingB TypeB;
loadFromCache(keyA, &somethingA, nil);
loadFromCache(keyB, &somethingB, nil);
fmt.Printf("Somethings: %v, %v", somethingA, somethingB);
}
func loadFromCache(key string, isNew, out interface {}, saveNewData interface {}) {
if err := cache.load(key, &out); err!=nil { // NOTE: Current issue is that this expects "&out" to be `TypeA`/`TypeB` not "interface {}", but I don't want to copy and paste this whole function's worth of code or whatever.
panic("oh no!");
}
if (saveNewData!=nil) {
cache.save(key, saveNewData); // This doesn't seem to care if "saveNewData" is "interface {}" when saving, but later cache fetches above using the "load()" method to an "interface {}"-typed `&out` parameter throw an exception that the "interface {}" type on `&out` does not match the original when it was saved here (`TypeA`/`TypeB`).
}
}
To change the type of an interface into its rightful type, you can use type assertions:
package main
import r "reflect"
type A struct {
Name string
}
func main() {
// No pointer
aa := A{"name"}
var ii interface{} = aa
bb := ii.(A)
// main.A
// Pointer
a := &A{"name"}
var i interface{} = a
b := *i.(*A)
// main.A
c := i.(*A)
// *main.A
d := r.Indirect(r.ValueOf(i)).Interface().(A)
// main.A
}
Playground 1
When using type assertions, you have to know the underlying type of your interface. In Go, there is no way to use type assertion with a dynamic type. reflect.Type is not a type, it's an interface representing a type. So no, you can't use it this way.
If you have several type possibilities, the solution is the type switch:
package main
import "fmt"
type TypeA struct {
A string
}
type TypeB struct {
B string
}
func doSomethingA(t TypeA) {
fmt.Println(t.A)
}
func doSomethingB(t TypeB) {
fmt.Println(t.B)
}
func doSomething(t interface{}) {
switch t := t.(type) {
case TypeA:
doSomethingA(t)
case TypeB:
doSomethingB(t)
default:
panic("Unrecognized type")
}
}
func main() {
a := TypeA{"I am A"}
b := TypeB{"I am B"}
doSomething(a)
// I am A
doSomething(b)
// I am B
}
Playground 2
It turns out that using JSON instead of Gob for serialization avoids the error that I was encountering entirely. Other functions can handle passing into interfaces, etc.

Why is errorString a struct, not a string

I am reading The Go Programming Language book and in it's description of the error package and the interface
package errors
type error interface {
Error() string
}
func New(text string) error { return &errorString{text} }
type errorString struct { text string }
func (e *errorString) Error() string { return e.text }
it says
The underlying type of errorString is a struct, not a string, to protect its representation from inadvertent (or premeditated) updates.
What does this mean? Wouldn't the package hide the underlying type since errorString isn't exported?
Update
Here is the test code I used implementing errorString using a string instead. Note that when try to use it from another package, you can't just assign a string as an error.
package testerr
type Error interface {
Error() string
}
func New(text string) Error {
return errorString(text)
}
type errorString string
func (e errorString) Error() string { return string(e) }
And testing it with the suggested codes
func main() {
err := errors.New("foo")
err = "bar"
fmt.Prinln(err)
}
Will end up producing an error when compiling
cannot use "bar" (type string) as type testerr.Error in assignment:
string does not implement testerr.Error (missing Error method)
Of course there is a downside to this since different errors that happen to have the same error string will evaluate to being equal which we don't want.
The book's explanation about "protecting representation from inadvertent updates" looks misleading to me. Whether errorString is a struct or a string, the error message is still a string and a string is immutable by specification.
This isn't a debate about uniqueness either. For example, errors.New("EOF") == io.EOF evaluates to false, although both errors have the exact same underlying message. The same would apply even if errorString was a string, as long as errors.New would return a pointer to it (see my example.)
You could say a struct implementing error is idiomatic since that's also how the standard library introduces custom errors. Take a look at SyntaxError from the encoding/json package:
type SyntaxError struct {
Offset int64 // error occurred after reading Offset bytes
// contains filtered or unexported fields
}
func (e *SyntaxError) Error() string { return e.msg }
(source)
Also, a struct implementing the error interface has no performance implications and does not consume more memory over a string implementation. See Go Data Structures.
Your testerr package works pretty well but it looses a major feature of the "struct-based" standard error package: That of un-equality:
package main
import ( "fmt"; "testerr"; "errors" )
func main() {
a := testerr.New("foo")
b := testerr.New("foo")
fmt.Println(a == b) // true
c := errors.New("foo")
d := errors.New("foo")
fmt.Println(c == d) // false
}
With errorString being a plain string different errors with the same string content become equal. The original code uses a pointer to struct and each New allocates a new struct so the different values returned from Neware different if compared with == albeit the equal error text.
No compiler is allowed to produce the same pointer here. And this feature of "different calls to New produce different error values" is important to prevent unintended equality of errors. Your testerr can be modified to yield this property by having *errorString implement Error. Try it: You need a temporary to take the address of. It "feels" wrong. One could imagine a fancy compiler which internalises the string values and might return the same pointer (as it points to the same internalised string) which would break this nice inequality property.

Instance new Type (Golang)

Can anyone tell me how to create a new instance of Type from a string? Reflect?
There are examples but they are for the older (pre Go 1 versions) of the language [:(]
So, if I understand your question correctly, you are asking about how you can create an object when you just have the name of the type as string. So, for example, you might have a string "MyStruct" and you want to create an object of this type.
Unfortunately, that's not easily possible because Go is a statically typed language and the linker will eliminate dead code (or inline parts of it). So, there is no guarantee, that your final executable will even contain the code of "MyStruct".
You can however, maintain a global map[string]reflect.Type manually. For example by initializing this map in the init() function of your packages which defines such discover-able types. This will also tell the compiler that you are using the types. Afterwards, you can use this map to look up the reflect.Type of the type you want to create and use reflect.New to get a pointer to a new object of that type (stored as a reflect.Value). You can extract the object into an interface with something like this:
reflect.New(yourtype).Elem().Interface()
Elem() will de-reference the pointer and Interface() will return the reflected value as an interface{}. See The Laws of Reflection for further details.
PS: There might be a better way to structure your program which doesn't even require reflection and which let the compiler catch more errors. Have you considered using a factory method for example? An other easy solution might be to maintain a map[string]func() interface{} of functions which can be invoked to create a new object with that name.
Factory with predefined constructors can be based on something like:
package main
import (
"fmt"
)
type Creator func() interface{}
type A struct {
a int
}
type B struct {
a bool
}
func NewA() interface{} {
return new(A)
}
func NewB() interface{} {
return new(B)
}
func main() {
m := map[string]Creator{}
m["A"] = NewA
m["B"] = NewB
for k, v := range m {
fmt.Printf("%v -> %v\n", k, v())
}
}

Resources