I will use cgo to wrap one c library as go library for the project usage. I read the document, it seems there are lots of rules while using cgo. I don't know whether this is legal or not.
Both LibCtx and Client is a struct in C. Is this a legal way to put C struct into a golang struct?
//DBClientLib.go
type DBClient struct {
Libctx C.LibCtx
LibClient C.Client
}
func (client DBClient) GetEntry(key string) interface{} {
//...
}
Yes, this is totally legal. Check out this short example:
package main
/*
typedef struct Point {
int x , y;
} Point;
*/
import "C"
import "fmt"
type CPoint struct {
Point C.Point
}
func main() {
point := CPoint{Point: C.Point{x: 1, y: 2}}
fmt.Printf("%+v", point)
}
OUTPUT
{Point:{x:1 y:2}}
Related
I'm trying to refactor some golang source code, and I would like to use interfaces but I find huge difficulties (bear with me, I'm a hard-core C/C++ orphan)
I extracted a small sample exhibiting the error I get
package main
import "fmt"
type LogProcessor interface {
Init() int
}
type MyProcessor struct {
a int
}
func (m MyProcessor) Init() int {
return m.a
}
func main() {
t := &(MyProcessor{2})
var p *LogProcessor = &(MyProcessor{4}) //!!!fails!!!
fmt.Println((*t).Init(), (*p).Init())
}
Why is the second assignment failing?
Adding the code modified to demonstrate what I was trying to do. I thought interfaces where more similar to C++ classes. My fault. Still learning
package main
import "fmt"
type LogProcessor interface {
Init() int
}
type MyProcessor struct {
a int
}
func (m *MyProcessor) Init() int {
m.a++
return m.a
}
func main() {
t := &(MyProcessor{2})
m := MyProcessor{4}
var p LogProcessor = &m
fmt.Println(t.Init(), p.Init())
fmt.Println(t.a, m.a)
}
The expression MyProcessor{2} is a composite literal. It is valid to take the address of a composite literal, and it will be of type *MyProcessor.
So here:
t := &(MyProcessor{2})
Type of t will be *MyProcessor.
Your failing line:
var p *LogProcessor = &(MyProcessor{4}) //!!!fails!!!
The type of the expression on the right hand side is again *MyProcessor. It's a pointer to a concrete type. The type of p is *LogProcessor, it's a pointer to another type. Assignability rules don't apply here, so the value is simply not assignable to the variable p.
Note that there is an assignability rule:
A value x is assignable to a variable of type T ("x is assignable to T") if one of the following conditions applies:
...
T is an interface type and x implements T.
In your example p's type is not an interface type, but a pointer to interface. You rarely (if ever) need this in go.
Instead if you use "just" the interface type:
var p LogProcessor = &(MyProcessor{4}) // This works!
This works because the concrete type *MyProcessor implements the interface type LogProcessor. You also don't need the parenthesis, you may simply use &MyProcessor{4}.
Then of course you can't dereference p (as it's not a pointer), so you have to use p.Init().
it is failing because you are using a pointer to an interface, if you remove the pointer to LogProcessor for var p it works
package main
import "fmt"
type LogProcessor interface {
Init() int
}
type MyProcessor struct {
a int
}
func (m MyProcessor) Init() int {
return 2
}
func main() {
t := &(MyProcessor{2})
var p LogProcessor = MyProcessor{4} // works without a pointer to the interface type
fmt.Println((*t).Init(), (p).Init())
}
Can an inline struct in Go be checked for emptiness?
The following example checks p, which is of type Person for emptiness.
It also defines the inline struct i. (How) can i be checked for emptiness?
package main
import (
"fmt"
)
type Person struct {
name string
}
func main() {
// Types can be checked for emptiness.
p := Person{}
if (p == Person{}) {
fmt.Println("Empty!")
}
// But: how to check for an empty inline struct?
// I.e. how to check, if i is empty?
var i struct {
value int
}
fmt.Println(i) // Required, or compiler will complain about unused 'i'.
}
I'm experimenting with using Go for creating dlls in Windows that I can import into Python but I'm having some issues with exporting functions that return a pointer to a Go struct. The following is a very stripped down example:
package main
import "C"
type data struct {
value1, value2 int
}
type PData *data
//export Callme
func Callme() PData {
var d PData = new (data)
return d
}
//export getValue1
func getValue1 (st PData) int {
return st.value1
}
func main() {
}
Note I also create a pointer type hoping this would end up as a simple handle on the C side. For the C side to access the struct I would provide helper routines (I provide one example) on the go side that would take a pointer to the struct as an argument. Unfortunately, the above code doesn't compile:
go build -o main.dll -buildmode=c-shared .\main.go
# command-line-arguments
.\main.go:5:11: Go type not supported in export: struct {
value1, value2 int
}
.\main.go:5:11: Go type not supported in export: struct {
value1, value2 int
}
.\main.go:5:11: Go type not supported in export: struct {
value1, value2 int
}
.\main.go:5:11: Go type not supported in export: struct {
value1, value2 int
}
Is this a limitation of Go? I've tried simple return values such as int and floats and they work ok.
Is there any way around it?
Based on https://golang.org/cmd/cgo/#hdr-C_references_to_Go:
Go struct types are not supported; use a C struct type.
Also check out the following Github issue:
https://github.com/golang/go/issues/18412
I'm trying to convert an interface dynamically back to it's original struct but I am having issues accessing attributes of the struct after the conversion.
Take this code for example.
package main
import (
"fmt"
"log"
)
type struct1 struct {
A string
B string
}
type struct2 struct {
A string
C string
}
type struct3 struct {
A string
D string
}
func main() {
s1 := struct1{}
s1.A = "A"
structTest(s1)
s2 := struct2{}
s2.A = "A"
structTest(s2)
s3 := struct3{}
s3.A = "A"
structTest(s3)
}
func structTest(val interface{}) {
var typedVal interface{}
switch v := val.(type) {
case struct1:
fmt.Println("val is struct1")
case struct2:
fmt.Println("val is struct2")
case struct3:
fmt.Println("val is struct3")
default:
log.Panic("not sure what val is.")
}
fmt.Println(typedVal.A)
}
I would like to be able to pass in one of 3 known struct types into my function. Then figure out which struct type was passed in to type assert it. Finally I want to be able to access like attributes.
Basically I want to have some basic inheritance in my structs, but so far it seems that it is not possible to do this in go. I saw some posts mentioning inheritance using an interface, but my structs have no methods so I'm not sure how I would use an interface.
Is something like this possible in go?
I would like to be able to pass in one of 3 known struct types into my function. Then figure out which struct type was passed in to type assert it. Finally I want to be able to access like attributes.
You can use type assertions to do exactly that. Basic idea is, in any case of the type switch just use type assertion to get a concrete instance of the corresponding type and then you can call whatever properties that you wish.
Take a look at the following example
package main
import (
"fmt"
)
type test1 struct {
A, B string
}
type test2 struct {
A, C string
}
func testType(val interface{}) {
switch val.(type) {
case test1:
t := val.(test1)
fmt.Println(t.B)
break
case test2:
t := val.(test2)
fmt.Println(t.C)
break
}
}
func main() {
t1, t2 := test1{B: "hello"}, test2{C: "world"}
testType(t1)
testType(t2)
}
Playground
Function structTest(val interface{}) in your code seems to be loosely typed. You pass it an untyped argument and expect it will satisfy some condition (will have field A), it looks strange in any typed language.
Using an interface this kind of polymorphism, in Go, to my mind, can be expressed something like
package main
import (
"fmt"
"log"
)
type A string
type HasA interface {
PrintA()
}
func (a A) PrintA() { fmt.Println(a) }
type struct1 struct {
A
B string
}
type struct2 struct {
A
C string
}
type struct3 struct {
A
D string
}
func main() {
s1 := struct1{}
s1.A = "A"
structTest(s1)
s2 := struct2{}
s2.A = "A"
structTest(s2)
s3 := struct3{}
s3.A = "A"
structTest(s3)
}
func structTest(val HasA) {
switch val.(type) {
case struct1:
fmt.Println("val is struct1")
case struct2:
fmt.Println("val is struct2")
case struct3:
fmt.Println("val is struct3")
default:
log.Panic("not sure what val is.")
}
val.PrintA()
}
Playground
I am fairly new to Go and I have been doing OOP for a long time. Now, I understand that inheritance is done via composition but ... I'd like to send a specialization in a function expecting a generalization as such:
package main
import (
"fmt"
)
type A struct {
ONE int
}
type B struct {
A
ANOTHER int
}
func main() {
fmt.Println("Hello, playground")
a := A{1}
b := B{a, 2}
fmt.Println(a.ONE)
fmt.Println(b.ANOTHER)
takeA(&b)
}
func takeA(a *A) {
fmt.Println(a.ONE)
}
Sure, I can do takeA(&b.A) but it defeats the hierarchy I am trying to set up as some A fields/method could be shadowed in B.
Is there a way around this? Or should I create a dumb interface such as:
package main
import (
"fmt"
)
type A struct {
ONE int
}
func (a A) getOne() int{
return a.ONE
}
type B struct {
A
ANOTHER int
}
type HasOne interface {
getOne() int
}
func main() {
fmt.Println("Hello, playground")
a := A{1}
b := B{a, 2}
fmt.Println(a.ONE)
fmt.Println(b.ANOTHER)
takeA(b)
}
func takeA(a HasOne) {
fmt.Println(a.getOne())
}
There is no inheritance in Go. Composition doesn't give you dynamic dispatch (which is usually implied when 'polymorphism' and 'inheritance' are used in the same paragraph): the embedded method call always happens on the embedded field as a receiver, not on the container type it is embedded into.