I'm trying an example related to struct embedding of interfaces
// https://talks.golang.org/2014/go4java.slide#52
// Struct embedding of interfaces
// https://play.golang.org/p/SYiZ7M1OEhU
package main
import (
"bytes"
"fmt"
"net"
)
// net.Conn has Read and Write
type loopBack struct {
net.Conn
buf bytes.Buffer
}
func (c *loopBack) Read(b []byte) (int, error) {
fmt.Println("loopBack Read")
return 0, nil
}
func main() {
loop := loopBack{}
loop.Read(nil)
loop.Write(nil)
}
and the Write method is undefined, so I get this runtime error
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0xffffffff addr=0x0 pc=0xe28ca]
goroutine 1 [running]:
main.main()
/tmp/sandbox812386031/main.go:28 +0x6a
Exist some way to validate it at compile time?
link to code
https://play.golang.org/p/SYiZ7M1OEhU
What you are doing is not the same as saying "loopBack implements net.Conn".
To get compile-time error(s) about the missing method – and the mismatched Read(), too – declare loop's type:
(And don't embed net.Conn in loopBack)
func main() {
var loop net.Conn = loopBack{}
Golang doesn't require exlicit interface implementations. What you do here:
type loopBack struct {
net.Conn
buf bytes.Buffer
}
Is the similar to:
type loopBack struct{
Conn net.Conn
buf bytes.Buffer
}
net.Conn being an interface type, the first field of your loopBack type can be anything that implements the net.Conn interface, which is of course more than Read and Write alone (see here).
The advantage of embedding types is that the fields and receiver functions (name conflicts aside) can be accessed directly on the types that embeds them.
With an embedded net.Conn field, you can indeed write:
loop.Write(nil)
If the Conn field is initialised (otherwise, its value is nil). Changing the declaration to the second version, loop.Write won't work, you'll have to write:
loop.Conn.Write(nil)
Type embedding is very powerful, but there's a number of gotcha's when you first get started. Thankfully, there's an entire paragraph explaining embedding on the effective go doc
Anyway, as stated, you are able to call functions, and access fields (if you're embedding a struct type instead of an interface). There is one thing, though: the field must be initialised correctly!
And that's where you went wrong: You still have to initialise your Conn part of the loopBack variable, otherwise what you're doing is the same as:
net.Conn(nil).Write(nil)
Which, naturally, results in a panic (nil pointer dereference)...
For example:
conn, err := net.Dial("tcp", "localhost:80")
if err != nil {
log.Fatalf("failed to dial localhost: %+v", err)
}
loop := loopBack{
Conn: conn,
}
loop.Write(nil) // same as conn.Write(nil)
Failing to set the net.Conn embedded field is akin to doing something like this:
s := make([]*int, 10) // make slice of 10 pointers to int
fmt.Println(len(s)) // outputs 10
*s[0]++ // add 1 to first element PANICS
The 10 elements in the slice exist, but they've all been initialised to nil
Related
I'm coming at Golang from a Python background and I am trying to wrap my head around various new concepts.
One thing I have come across is this function in net.go:
func (c *conn) ok() bool { return c != nil && c.fd != nil }
This function is called by multiple net.go methods, e.g. conn.Read:
// Read implements the Conn Read method.
func (c *conn) Read(b []byte) (int, error) {
if !c.ok() {
return 0, syscall.EINVAL
}
I am trying to understand how the ok() method can be called on conn, despite the fact that ok() does not appear to be an interface of conn.
Certainly I do not seem to be able to call ok() from my client code:
func main() {
conn, err := net.Dial("tcp", "www.reddit.com:80")
if err != nil {
os.Exit(-1)
}
fmt.Println(&conn.ok())
}
Output:
./server.go:14:22: conn.ok undefined (type net.Conn has no field or method ok)
Any pointers appreciated...
From Go document :
An identifier may be exported to permit access to it from another
package. An identifier is exported if the first character of the
identifier's name is a Unicode upper case letter
So , ok function is not exported and you can't access it outside of net package.
Go does not use public/private keywords for visibility of an identifier. If the initial character is an upper case letter, the identifier is exported(public); otherwise it is not:
upper case initial letter: Name is visible to clients of package
otherwise: name (or _Name) is not visible to clients of package
There is no field or method like ok in net.Conn that what the error says and that is correct.
when you try to read and write into the conn , you would get err and number of bytes read or write it into the connection.
I need to write a golang plugin with a function that accepts an array of golang bytes, but when I try to call this function after loading the plugin in the client code, it always gives me
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x40b22af]
Any suggestions on how to resolve this?
code to reproduce(highly simplified, but the same error occurs)
client.go
package main
import (
"plugin"
"log"
)
type T interface {
sayHi(data []byte)
}
func main() {
plgin, _ := plugin.Open("./plugin.so")
symbol, _ := plgin.Lookup("Endpoint")
b, _ := symbol.(T)
log.Println("From main")
data := []byte{1,2,3,4,5}
b.sayHi(data)
}
plugin.go(this program is built with buildmode=plugin)
package main
import (
"log"
)
type dummy struct {}
func (d dummy)sayHi(data []byte) {
log.Println("From plugin")
log.Println(data)
}
var Endpoint dummy
func main() {
}
First, you should always check returned errors (and the result of type assertion from the plugin symbol)!
The problem in your case is that the sayHi() method is unexported. So if you create an interface in your app, it will not match the unexported method created in the plugin.
Export the method, and it will work (given you don't get any other errors).
In the plugin:
func (d dummy) SayHi(data []byte) {
log.Println("From plugin")
log.Println(data)
}
In your main app:
type T interface {
SayHi(data []byte)
}
And when calling it:
b.SayHi(data)
One thing to note here. When you lookup a variable from a plugin, you get a pointer to the variable (else you could not change its value). For details, see: Plugin symbol as function return. What this means is that symbol will be of type *dummy, not dummy. This doesn't cause any troubles here, as the method set of *dummy also contains the SayHi() method, just like the method set of dummy, but you should not forget about this if you would attempt to type-assert a non-interface type (a concrete type) out of a plugin symbol.
I'm using gob to serialize structs to disk. The struct in question contains an interface field, so the concrete type needs to be registered using gob.Register(...).
The wrinkle here is that the library doing the gob-ing should be ignorant of the concrete type in use. I wanted the serialization to be possible even when callers have defined their own implementations of the interface.
I can successfully encode the data by registering the type on the fly (see trivial example below), but upon trying to re-read that data, gob refuses to accept the un-registered type. Its frustrating, because it feels like all the data is there - why isn't gob just unpacking that as a main.UpperCaseTransformation struct if it's labelled as such?
package main
import (
"encoding/gob"
"fmt"
"os"
"strings"
)
type Transformation interface {
Transform(s string) string
}
type TextTransformation struct {
BaseString string
Transformation Transformation
}
type UpperCaseTransformation struct{}
func (UpperCaseTransformation) Transform(s string) string {
return strings.ToUpper(s)
}
func panicOnError(err error) {
if err != nil {
panic(err)
}
}
// Execute this twice to see the problem (it will tidy up files)
func main() {
file := os.TempDir() + "/so-example"
if _, err := os.Stat(file); os.IsNotExist(err) {
tt := TextTransformation{"Hello, World!", UpperCaseTransformation{}}
// Note: didn't need to refer to concrete type explicitly
gob.Register(tt.Transformation)
f, err := os.Create(file)
panicOnError(err)
defer f.Close()
enc := gob.NewEncoder(f)
err = enc.Encode(tt)
panicOnError(err)
fmt.Println("Run complete, run again for error.")
} else {
f, err := os.Open(file)
panicOnError(err)
defer os.Remove(f.Name())
defer f.Close()
var newTT TextTransformation
dec := gob.NewDecoder(f)
// Errors with: `gob: name not registered for interface: "main.UpperCaseTransformation"'
err = dec.Decode(&newTT)
panicOnError(err)
}
}
My work-around would be to require implementers of the interface to register their type with gob. But I don't like how that reveals my serialization choices to the callers.
Is there any route forward that avoids this?
Philosophical argumentation
The encoding/gob package cannot (or rather should not) make that decision on its own. Since the gob package creates a serialized form independent of / detached from the app, there is no guarantee that values of interface types will exist in the decoder; and even if they do (matched by the concrete type name), there is no guarantee that they represent the same type (or the same implementation of a given type).
By calling gob.Register() (or gob.RegisterName()) you make that intent clear, you give green light to the gob package to use that type. This also ensures that the type does exist, else you would not be able to pass a value of it when registering.
Technical requirement
There's also a technical point of view that dictates this requirement (that you must register prior): you cannot obtain the reflect.Type type descriptor of a type given by its string name. Not just you, the encoding/gob package can't do it either.
So by requiring you to call gob.Register() prior, the gob package will receive a value of the type in question, and therefore it can (and it will) access and store its reflect.Type descriptor internally, and so when a value of this type is detected, it is capable of creating a new value of this type (e.g. using reflect.New()) in order to store the value being decoded into it.
The reason why you can't "lookup" types by name is that they may not end up in your binary (they may get "optimized out") unless you explicitly refer to them. For details see Call all functions with special prefix or suffix in Golang; and Splitting client/server code. When registering your custom types (by passing values of them), you are making an explicit reference to them and thus ensuring that they won't get excluded from the binaries.
I am trying to understand the code that is used at my company. I am new to go lang, and I have already gone through the tutorial on their official website. However, I am having a hard time wrapping my head around empty interfaces, i.e. interface{}. From various sources online, I figured out that the empty interface can hold any type. But, I am having a hard time figuring out the codebase, especially some of the functions. I will not be posting the entire thing here, but just the minimal functions in which it has been used. Please bear with me!
Function (I am trying to understand):
func (this *RequestHandler) CreateAppHandler(rw http.ResponseWriter, r *http.Request) *foo.ResponseError {
var data *views.Data = &views.Data{Attributes: &domain.Application{}}
var request *views.Request = &views.Request{Data: data}
if err := json.NewDecoder(r.Body).Decode(request); err != nil {
logrus.Error(err)
return foo.NewResponsePropogateError(foo.STATUS_400, err)
}
requestApp := request.Data.Attributes.(*domain.Application)
requestApp.CreatedBy = user
Setting some context, RequestHandler is a struct defined in the same package as this code. domain and views are seperate packages. Application is a struct in the package domain. The following two structs are part of the package views:
type Data struct {
Id string `json:"id"`
Type string `json:"type"`
Attributes interface{} `json:"attributes"`
}
type Request struct {
Data *Data `json:"data"`
}
The following are part of the package json:
func NewDecoder(r io.Reader) *Decoder {
return &Decoder{r: r}
}
func (dec *Decoder) Decode(v interface{}) error {
if dec.err != nil {
return dec.err
}
if err := dec.tokenPrepareForDecode(); err != nil {
return err
}
if !dec.tokenValueAllowed() {
return &SyntaxError{msg: "not at beginning of value"}
}
// Read whole value into buffer.
n, err := dec.readValue()
if err != nil {
return err
}
dec.d.init(dec.buf[dec.scanp : dec.scanp+n])
dec.scanp += n
// Don't save err from unmarshal into dec.err:
// the connection is still usable since we read a complete JSON
// object from it before the error happened.
err = dec.d.unmarshal(v)
// fixup token streaming state
dec.tokenValueEnd()
return err
}
type Decoder struct {
r io.Reader
buf []byte
d decodeState
scanp int // start of unread data in buf
scan scanner
err error
tokenState int
tokenStack []int
}
Now, I understood that, in the struct Data in package views, Application is being set as a type for the empty interface. After that, a pointer to Request in the same package is created which points to the variable data.
I have the following doubts:
What exactly does this keyword mean in Go? What is the purpose of writing this * RequestHandler?
Initialization of a structure in Go can be done while assigning it to a variable by specifying the values of all it's members. However, here, for the struct Data, only the empty interface value is assigned and the values for the other two fields are not assigned?
What is the advantage of assigning the Application struct to an empty interface? Does it mean I can use the struct members using the interface variable directly?
Can someone help me figure out the meaning of this statement? json.NewDecoder(r.Body).Decode(request)?
While I know this is too much, but I am having a hard time figuring out the meaning of interfaces in Go. Please help!
this is not a keyword in go; any variable name can be used there. That is called the receiver. A function declared in that way must be called like thing.func(params), where "thing" is an expression of the type of the receiver. Within the function, the receiver is set to the value of thing.
A struct literal does not have to contain values for all the fields (or any of them). Any fields not explicitly set will have the zero value for their types.
As you said, an empty interface can take on a value of any type. To use a value of type interface{}, you would use type assertion or a type switch to determine the type of the value, or you could use reflection to use the value without having to have code for the specific type.
What specifically about that statement do you not understand? json is the name of a package in which the function NewDecoder is declared. That function is called, and then the Decode function (which is implemented by the type of the return value of NewDecoder) is called on that return value.
You may want to take a look at Effective Go and/or The Go Programming Language Specification for more information.
Create a struct that implements an interface.
Encapsulate it into another struct.
Fetch the struct / dereference it.
Fetching gets pointer to the implementation of the interface.
Dereferencing the pointer results in another point to the interface.
Why wouldn't dereferencing the pointer to the implementation gives the implementation instance?
package main
import (
"fmt"
"net/http"
"golang.org/x/net/http2"
)
func main() {
transport := &http2.Transport{}
client := &http.Client{Transport: transport}
tmp1 := client.Transport
tmp2 := &client.Transport
tmp3 := &tmp1
fmt.Printf("%T\n%T\n%T\n", tmp1, tmp2, tmp3)
//dialTLS := tmp1.DialTLS
}
This code outputs...
*http2.Transport
*http.RoundTripper
*http.RoundTripper
As well, trying to access a property of the tmp1 (uncommenting dialTLS := tmp1.DialTLS) results in compile error...
tmp1.DialTLS undefined (type http.RoundTripper has no field or method DialTLS)
...even though fmt.Printf("%+v", tmp1) outputs...
&{DialTLS:<nil> TLSClientConfig:0xc8203ec8c0 ConnPool:<nil> DisableCompression:false MaxHeaderListSize:0 t1:<nil> connPoolOnce:{m:{state:0 sema:0} done:0} connPoolOrDef:<nil>}
What I am attempting to do is access DialTLS in the Transport instance.
You have a type mismatch here. If you look at the documentation, you'll see that the field Transport of the Client struct returns an interface RoundTripper:
type Client struct {
// Transport specifies the mechanism by which individual
// HTTP requests are made.
// If nil, DefaultTransport is used.
Transport RoundTripper
// ...
}
So, the type of tmp1 is http.RoundTripper, though the underlying type is *http2.Transport which implements the RoundTripper interface.
As for tmp2 and tmp3, they are seen as pointers to a RoundTripper and not as **http2.Transport.
In order to retrieve the DialTLS field, you have to use type assertions to convert a RoundTripper back into a Transport:
dialTLS := client.Transport.(*http2.Transport).DialTLS