testing function calling using var declaration to mock the result - go

I'm testing a function which called another function in Go. And here's what I have
package b
type b struct {...}
func (b *b) functionB(){...}
package a
import "b"
type a struct {...}
func (a *a) functionA() {
b := b{...}
b.functionB()
...
}
I want to modify the function declaration in b like this:
package b
type b struct {...}
var functionB = b.FuncInB
func (b *b) FuncInB(){...}
so that I can mock the return of functionB in a. However, I got error message in a that says b.functionB is undefined because it should be the function of b object. How can I make this work?

If you want to use a definition of one package in another package you have to export it. This is done by letting the definition start with a capital letter. Your type should be defined like this:
type B struct {...}
You cannot access a function via its type. This line
var functionB = b.FuncInB
will not work, as you can refer to the function only from an existing struct. You shoule remove this line and call it differently (see below).
Your package a has now two minor issues. When you want to use struct B from package b you have to either refer to it like this b.B
import "b"
b.B{...}
or make a dot import for package b:
import . "b"
B{...}
The last thing is, that you shadow the package name when assigning a variable with the same name as the package. In that, you should use a different variable name:
func (a *a) functionA() {
myB := b{...}
myB.FunctionB()
...
}
So in the end, your packages should look like this:
package b
type B struct {
// ...
}
func (b *B) FuncInB() {
// ...
}
package a
import "b"
type a struct {
// ...
}
func (a *a) functionA () {
myB := B {
// ...
}
myB.functionB()
// ...
}

Related

Getting "implicit assignment of unexported field"

package main
main.go
import (
"fmt"
"practice/pkg"
)
func main() {
mk := pkg.MustKey{map[string]string{"Hello": "bar"}}
fmt.Printf("%v\n", mk)
}
pkg package
hello.go
package pkg
type MustKey struct {
m map[string]string
}
While executing the following, I am getting error as mentioned in the subject line. Any help will be appreciated.
There is a very important rule in Go - how to Export/unexport any functions/methods/fields.
Export - when the name starts with a Captial letter (say it Public)
unexport - when the name starts with a small letter (say it Private)
So in your case, the struct type name MustKey is exportable (starts with a capital M) and can be accessed outside your defined package pkg. But the map variable m inside the struct does start with a small m, so it cannot be accessed outside the package and private to that package only.
So, you have 2 solutions:
Either use M instead of m, like:
type MustKey struct {
M map[string]string
}
Or, if you still want the map variable private - use Exported methods with helping of interface
type MustKey struct {
m map[string]string
}
func (mk *MustKey) GetValue(key string) (string, error) {
value, ok := m[key]
if !ok {
return "", fmt.Errorf("Key is not available: %s", key)
}
return value, nil
}
func (mk *MustKey) SetValue(key, value string) {
m[key] = value
}
And you can use these Get and Set methods to put your own logic.
Read this for good understanding.
In this code:
type MustKey struct {
m map[string]string
}
the map variable is in lower case so it is un-exported (and only private to that package). In Golang to export any field from one pkg to another it should me in Upper case.
Two solutions:
1) Declare Map fields in Upper case, eg:
type MustKey struct {
// m map[string]string
// Upper case fields can be export to other packages
M map[string]string
}
2) Wrap your structure in one function and export the function name.
MustKey.m is an unexported field. You are attempting to initialize that field without referring to it by name with pkg.MustKey{map[string]string{"Hello": "bar"}}.
You either have to export the field by renaming it to M, or you have to define a constructor function that will set it in the package:
func NewMustKey(m map[string]string) MustKey {
return MustKey{m:m}
}
The field m in the MustKey struct is lower case. Therefore it is an unexported field and cannot be used by a program that imports the pkg package. Unexported fields have to be operated on by methods or functions that are internal to the pkg package. Or change it to an M and then use that externally.
You are implicitly using m when you do the initialization in main.

golang: implicit vs explicit func definition

Consider this package:
package A
var X="change me"
var Y=func(i int) int { return i*i) }
func Z(i int) int { return -i) }
The two explicit variables (X,Y) can be changed in another package, say main...
package main
import "A"
func main () {
A.X="done"
A.Y=func (i int) int { return i*i*i }
print(A.X,A.Y(7))
//... but A.Z apparently can't be changed.
//A.Z=func (int i) int { return i*i*i } //main.go:8: cannot assign to A.Z
}
Obviously there's a difference between defining a func variable (like Y) and an explicit func (like Z). I have googled this but not found much in the way of enlightenment. It almost seems as if var SomeFunc=func (...) defines indeed a variable, but func SomeFunc(...) defines a constant.
PS: A small goodie I found while researching this which I have not seen mentioned in the Go books I've read so far. A dot before a package import imports names without them having to be qualified:
package main
import . "A"
func main () {
X="done"
Y=func (i int) int { return i*i*i }
print(X,Y(7))
}
func SomeFunc(), in essence creates a strong/constant/immutable binding of the identifier SomeFunc to the function you define. When you create a variable like so:
var (
SomeFunc = func(i int) int {
return i * 2
}
)
You create a global variable of the type func(int) int. You can reassign this variable later on. This is something you can't really do with a func SomeFunc identifier. Simply put, this is because func SomeFunc() binds the function Directly to the identifier. The var SomeFunc approach creates a variable (type func(int) int in this case), and that variable is initialised using the function you're assigning. As is the case with variables: reassignment is possible.
Example
What you can do with functions, is shadow them using a scoped variable. This will probably get flagged by most linters, but it's a technique/trick that sometimes can be useful in testing
Example
As for the dot-imports: Please don't do that unless there's a very, very, very good reason for it. A good reason would be you writing a package that adds to an existing one, so you no longer import an existing one, but import your own. Think of it as extending a package. 99% of the time. Don't, whatever you do, use it to quench errors when you import encoding/json to add json serialization annotations to a struct. In those cases, use an underscore:
package foo
import (
"encoding/json"
)
type Bar struct {
Foobar string `json:"foobar"`
}
func New() *Bar {
&Bar{"Default foobar"}
}
Don't know about golang 1.8, but packages like that could result in compiler errors (package encoding/json imported but not used). To silence that error, you simply changed the import to:
import(
_ "encoding/json"
)
The dot-packages, underscores, and package aliases all follow the same rule: use them as little as possible.
Code used in examples:
package main
import (
"fmt"
)
var (
SomeFunc = func(i int) int {
return i * 2
}
)
func main() {
fmt.Println(SomeFunc(2)) // output 4
reassign()
fmt.Println(SomeFunc(2)) // output 8
shadowReassign()
fmt.Println(SomeFunc(2)) // output 2
}
// global function
func reassign() {
// assign new function to the global var. Function types MUST match
SomeFunc = func(i int) int {
return i * 4
}
}
// assign function to local reassign variable
func shadowReassign() {
reassign := func() {
// same as global reassign
SomeFunc = func(i int) int {
return i
}
}
reassign()
}
There's a difference between declaring a variable initialized with a function value:
var Y=func(i int) int { return i*i) }
and declaring a function:
func Z(i int) int { return -i) }
The specification says this about declarations:
A declaration binds a non-blank identifier to a constant, type, variable, function, label, or package.
The specification also says:
A function declaration binds an identifier, the function name, to a function.
The declaration of Y binds a variable to the name. This variable is initialized with a function value. The declaration of Z binds a function to the name.
If an explicit period (.) appears instead of a name, all the package's exported identifiers declared in that package's package block will be declared in the importing source file's file block and must be accessed without a qualifier.

Implicit interface conversion in golang

Here is an example of the idea I want to demonstrate.
package main
import "fmt"
// interface declaration
//
type A interface {
AAA() string
}
type B interface{
Get() A
}
// implementation
//
type CA struct {}
// implementation of A.AAA
func (ca *CA) AAA() string {
return "it's CA"
}
type C struct {}
// implementation of B.Get, except for returning a 'struct' instead of an 'interface'
func (c *C) Get() *CA {
return &CA{}
}
func main() {
var c interface{} = &C{}
d := c.(B)
fmt.Println(d.Get().AAA())
fmt.Println("Hello, playground")
}
In this example
interface B has a method Get to return an interface A
struct C has a member function Get to return a pointer to struct CA, which implements interface A
The result is Go can't deduce interface B from struct C, even their Get method is only different in returning type, which is convertible.
The reason I raise this question is when interface A, B and struct C, CA are in different packages, I can only:
refine the Get method of C to func Get() A, which introduce some dependency between packages.
refine both Get method of interface B and struct C to func Get() interface{}
I want to avoid dependency between packages and try not to rely on interface{}, can anyone give me some hint? What's the best practice in Go?
Your current *C type does not implement the interface B, therefore you can't assign a value of *C to a variable of type B nor can't you "type assert" a value of B from something holding a value of type *C.
Here's what you can do. Since you're already using a struct literal (&C{}), you may declare c to be of type *C of which you can call its Get() method, and you can convert the return value of C.Get() to A (because the return value does implement A):
var c *C = &C{}
var a A = c.Get() // This is ok, implicit interface value creation (of type A)
fmt.Println(a.AAA())
// Or without the intermediate "a", you can simply call:
fmt.Println(c.Get().AAA())
Output:
it's CA
it's CA
Or refactor:
The problem is that you have an interface (B) which you want to implement, which has a method which returns another interface (A). To implement this B interface, you have to have dependency to the package that defines A, you can't avoid this. And you have to declare C.Get() to return A (instead of a concrete struct type).
You may move A to a 3rd package and then the package that defines C will only have to depend on this 3rd package, but will not depend on the package that defines B (but still will implicitly implement the interface type B).

golang: can i share C.int between packages

in the main package i have:
var foo C.int
foo = 3
t := fastergo.Ctuner_new()
fastergo.Ctuner_register_parameter(t, &foo, 0, 100, 1)
in the fastergo package i have:
func Ctuner_register_parameter(tuner unsafe.Pointer, parameter *C.int, from C.int, to C.int, step C.int) C.int {
...
}
if i try to run it, i get:
demo.go:14[/tmp/go-build742221968/command-line-arguments/_obj/demo.cgo1.go:21]: cannot use &foo (type *_Ctype_int) as type *fastergo._Ctype_int in function argument
i am not really sure what go is trying to tell me here, but somehow i think it wants to tell me, that all C.int are not equal? why is this the case? how can i solve this / work around?
Since _Ctype_int doesn't begin with a Unicode upper case letter, the type is local to the package. Use Go types, except in the C wrapper package where you convert them to C types. The wrapper package should hide all the implementation details.
You don't provide sufficient information for us to create sample code which compiles and runs. Here's a rough outline of what I expected to see:
package main
import "tuner"
func main() {
var foo int
foo = 3
t := tuner.New()
t.RegisterParameter(&foo, 0, 100, 1)
}
.
package tuner
import (
"unsafe"
)
/*
#include "ctuner.h"
*/
import "C"
type Tuner struct {
ctuner uintptr
}
func New() *Tuner {
var t Tuner
t.ctuner = uintptr(unsafe.Pointer(C.ctuner_new()))
return &t
}
func (t *Tuner) RegisterParameter(parameter *int, from, to, step int) error {
var rv C.int
rv = C.ctuner_register_parameter(
(*C.ctuner)(unsafe.Pointer(t.ctuner)),
(*C.int)(unsafe.Pointer(parameter)),
C.int(from),
C.int(to),
C.int(step),
)
if rv != 0 {
// handle error
}
return nil
}
As explained by peterSO, you can't pass C.int between packages. However, you can pass pointers between packages by converting the pointer type. To do this, you would define a named type in the target package, import that type into the calling package and covert via unsafe.Pointer. There isn't any point in doing this with a single int.
However, it is helpful if you keep code to convert complex types in a package; for example an array of strings (or any sort of nested array).
The example below is for exporting a go function to be called in C, but this works in reverse, ie. if you want to call a C functions which a returns nested array.
package convert
import "C"
type PP_char **C.char
func From_c_to_go(arr_str PP_char, length int) []string {
// Some operation on the Ctype
var slice []string
for _, s := range unsafe.Slice(arr_str, length) {
if s == nil {
break
}
x := C.GoString(s)
slice = append(slice, x)
}
return slice
}
package main
import "C"
import "convert"
//export myFunc
func myFunc(arr_str **C.char, length int){
retyped_arr_str := convert.PP_char(unsafe.Pointer(arr_str))
slice := convert.From_c_to_go(retyped_arr_str, length)
// Do something with slice
}
You could instead decide to pass instance of unsafe.Pointer as an argument to the go function in the target package and perform the type conversion in that function.

Using function names as parameters

In Go, you can pass functions as parameters like callFunction(fn func). For example:
package main
import "fmt"
func example() {
fmt.Println("hello from example")
}
func callFunction(fn func) {
fn()
}
func main() {
callFunction(example)
}
But is it possible to call a function when it's a member of a struct? The following code would fail, but gives you an example of what I'm talking about:
package main
import "fmt"
type Example struct {
x int
y int
}
var example Example
func (e Example) StructFunction() {
fmt.Println("hello from example")
}
func callFunction(fn func) {
fn()
}
func main() {
callFunction(example.StructFunction)
}
(I know what I'm trying to do in that example is a little odd. The exact problem I have doesn't scale down to a simple example very well, but that's the essence of my problem. However I'm also intrigued about this from an academic perspective)
Methods (which are not "members of a struct" but methods of any named type, not only structs) are first class values. Go 1.0.3 didn't yet implemented method values but the tip version (as in the comming Go 1.1) has support method values. Quoting the full section here:
Method values
If the expression x has static type T and M is in the method set of type T, x.M is called a method value. The method value x.M is a function value that is callable with the same arguments as a method call of x.M. The expression x is evaluated and saved during the evaluation of the method value; the saved copy is then used as the receiver in any calls, which may be executed later.
The type T may be an interface or non-interface type.
As in the discussion of method expressions above, consider a struct type T with two methods, Mv, whose receiver is of type T, and Mp, whose receiver is of type *T.
type T struct {
a int
}
func (tv T) Mv(a int) int { return 0 } // value receiver
func (tp *T) Mp(f float32) float32 { return 1 } // pointer receiver
var t T
var pt *T
func makeT() T
The expression
t.Mv
yields a function value of type
func(int) int
These two invocations are equivalent:
t.Mv(7)
f := t.Mv; f(7)
Similarly, the expression
pt.Mp
yields a function value of type
func(float32) float32
As with selectors, a reference to a non-interface method with a value receiver using a pointer will automatically dereference that pointer: pt.Mv is equivalent to (*pt).Mv.
As with method calls, a reference to a non-interface method with a pointer receiver using an addressable value will automatically take the address of that value: t.Mv is equivalent to (&t).Mv.
f := t.Mv; f(7) // like t.Mv(7)
f := pt.Mp; f(7) // like pt.Mp(7)
f := pt.Mv; f(7) // like (*pt).Mv(7)
f := t.Mp; f(7) // like (&t).Mp(7)
f := makeT().Mp // invalid: result of makeT() is not addressable
Although the examples above use non-interface types, it is also legal to create a method value from a value of interface type.
var i interface { M(int) } = myVal
f := i.M; f(7) // like i.M(7)
Go 1.0 does not support the use of bound methods as function values. It will be supported in Go 1.1, but until then you can get similar behaviour through a closure. For example:
func main() {
callFunction(func() { example.StructFunction() })
}
It isn't quite as convenient, since you end up duplicating the function prototype but should do the trick.
I fixed your compile errors.
package main
import "fmt"
type Example struct {
x, y float64
}
var example Example
func (e Example) StructFunction() {
fmt.Println("hello from example")
}
func callFunction(fn func()) {
fn()
}
func main() {
callFunction(example.StructFunction)
}
Output:
hello from example
To add to #zzzz great answer (and the one given at https://golang.org/ref/spec#Method_values) here is an example that creates a method value from a value of an interface type.
package main
import "fmt"
type T struct{}
func (T) M(i int) { fmt.Println(i) }
func main() {
myVal := T{}
var i interface{ M(int) } = myVal
f := i.M
f(7) // like i.M(7)
}

Resources