multiple-value in single-value context no return func - go

I have a func in Go that simply writes to a buffer. I have no return type set on the func so I am not sure why I am seeing this error. Here is my code:
func Write(buffer *bytes.Buffer, values ...string) {
for _, val := range values
_, err := *buffer.WriteString(val)
if err != nil {
// print error
}
}
_, err := *buffer.WriteString(" ")
if err != nil {
// print error
}
}
It complains at both lines where I have buffer.WriteString. This leads me to believe it has something to do with the return types of the WriteString method on the buffer but I am not experienced enough in Go to know for sure.
Any help would be appreciated.
Edit: Updated code.

You don't need to dereference pointers to call methods in Go. The * operator before buffer.WriteString is applied to the returned values. To dereference buffer you would need to write (*buffer).WriteString, but that's not needed at all:
func Write(buffer *bytes.Buffer, values ...string) {
for _, val := range values {
_, err := buffer.WriteString(val)
if err != nil {
// print error
}
}
_, err := buffer.WriteString(" ")
if err != nil {
// print error
}
}

Related

gomock, Go,mango package ,MongoMock

I am trying to mock the below method using gomock
func GetS(tenantName string) (*mgo.Session, error) {
ctx := apiContext.TContext{}
url, err := connectionURLList.get(tenantName)
if err != nil {
log.GenericWarning(ctx,
fmt.Sprintf("connection to %s not yet created, creating one: %v", tenantName, err), nil)
if err := connectMongo(tenantName); err == nil {
return GetS(tenantName) //singleton recursion to again call GetS
}
return nil, err
}
// ignoring error, expected we will always setting session in session map
session, _ := connectionList.get(url)
return session.Copy(), err
}
My Interface
type MongoManager interface {
GetS(tenantName string)
}
func TestGetS(t *testing.T) {
//var mgoCall *mgo.Session
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
mockManagerObj := mocks.NewMockMongoManager(mockCtrl)
mockManagerObj.EXPECT().GetS("cacargroup").Return(nil)
}
I am Getting the below error . Can someone help
$ go test
--- FAIL: TestGetS (0.00s)
mongoManager_test.go:20: missing call(s) to *mocks.MockMongoManager.GetS(is equal to cacargroup) /Users/charles/workspace/src/bitbucket.org/tekion/tbaas/mongoManager/mongoManager_test.go:16
mongoManager_test.go:20: aborting test due to missing call(s) FAIL exit status 1
You see actually the method in your interface implemented with return type of an error. But you are using like it returns nothing and chaining the implementation. Just remove the return type of GetS.
type fn func(string) (*mgo.Session, error)
type MongoManager interface {
NewFunction(GetS, "cascade")
}
func TestGetS(t *testing.T) {
//var mgoCall *mgo.Session
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
mockManagerObj := mocks.NewMockMongoManager(mockCtrl)
mockManagerObj.EXPECT().GetS("cacargroup").Return(nil)
}
Also you have to remove it from GetS function too
func NewFunction(GetS fn, value string){
GetS("cascade")
}
func GetS(tenantName string) (*mgo.Session, error){
ctx := apiContext.TContext{}
url, err := connectionURLList.get(tenantName)
if err != nil {
log.GenericWarning(ctx,
fmt.Sprintf("connection to %s not yet created, creating one: %v", tenantName, err), nil)
if err := connectMongo(tenantName); err == nil {
return GetS(tenantName) //singleton recursion to again call GetS
}
return nil, err
}
// ignoring error, expected we will always setting session in session map
session, _ := connectionList.get(url)
}

Custom json unmarshaler return empty fields

I've implemented a custom JSON unmarshaler, but for some reason it won't return the proper value -all fields come back nil.
For example:
type test struct {
t string
}
func New(data string) (*test, error) {
return &test{t: data}, nil
}
func (t *test) UnmarshalJSON(b []byte) error {
tt, err := New(string(b))
if err != nil {
return err
}
t = tt
return nil
}
func main() {
str := `"hello"`
b := []byte(str)
t := &test{}
err := json.Unmarshal(b, t)
if err != nil {
fmt.Printf("unmarshal error occurred: %#v", err)
}
fmt.Printf("%#v", t)
}
https://play.golang.org/p/LuXkZQZHWz
The above code shows the output: &main.test{t:""}
Why doesn't it unmarshal the fields? i.e &main.test{t:"hello"}
Only when I dereference the pointers above, do I get the desired result.
i.e -
func (t *test) UnmarshalJSON(b []byte) error {
tt, err := New(string(b))
if err != nil {
return err
}
*t = *tt
return nil
}
You're assigning the local variable t, a pointer to test, to the value of the local variable tt, also a pointer to test. This has no effect on the value the original pointer t pointed to. You have to dereference the pointers to change the value it points to, rather than changing the local pointer itself:
*t = *tt

Idiomatic Go Happy Path

Suppose we have a function that returns some value and an error. What's the preferred way of handling the error and value declarations?
func example_a(data interface{}) (interface{}, error) {
var err error
var bytes []byte
if bytes, err = json.Marshal(data); err != nil {
return nil, err
}
// ...
return use(bytes), nil
}
func example_b(data interface{}) (interface{}, error) {
if bytes, err := json.Marshal(data); err != nil {
return nil, err
} else {
// ...
return use(bytes), nil
}
}
func example_c(data interface{}) (result interface{}, err error) {
var bytes []byte
if bytes, err = json.Marshal(data); err != nil {
return
}
// ...
return use(bytes), nil
}
func example_d(data interface{}) (interface{}, error) {
bytes, err := json.Marshal(data)
if err != nil {
return nil, err
}
// ...
return use(bytes), nil
}
func example_dream(data interface{}) (interface{}, error) {
if bytes, err ≡ json.Marshal(data); err != nil {
return nil, err
}
// ...
return use(bytes), nil
}
Example A is clear, but it adds 2 extra lines. Moreover, I find that it's unclear why in this particular case we should use var, and at the same time := is not always appropriate. Then you want to reuse the err declaration somewhere down the line, and I'm not a big fan of splitting declaration and assignment.
Example B is using the if-declare-test language feature, which I surmise is encouraged, but at the same time you are forced to nest function continuation violating the happy-path principle, which too is encouraged.
Example C uses the named parameter return feature, which is something between A and B. Biggest problem here, is that if your code base is using styles B and C, then it's easy to mistake := and =, which can cause all kinds of issues.
Example D (added from suggestions) has for me the same kind of usage problem as C, because inevitably I run into the following:
func example_d(a, b interface{}) (interface{}, error) {
bytes, err := json.Marshal(a)
if err != nil {
return nil, err
}
bytes, err := json.Marshal(b) //Compilation ERROR
if err != nil {
return nil, err
}
// ...
return use(bytes), nil
}
So depending on previous declarations I have to modify my code to either use := or =, which makes it harder to see and refactor.
Example Dream is what I kind of intuitively would have expected from GO - no nesting, and quick exit without too much verbosity and variable reuse. Obviously it doesn't compile.
Usually use() is inlined and repeats the pattern several times, compounding the nesting or split declaration issue.
So what's the most idiomatic way of handling such multiple returns and declarations? Is there a pattern I'm missing?
If you look at lots of Go code you will find the following to be the usual case:
func example(data interface{}) (interface{}, error) {
bytes, err := json.Marshal(data)
if err != nil {
return nil, err
}
// ...
return use(bytes), nil
}
The declare and test if construct is nice in its place, but it is not generally apropriate here.

Golang most efficient way to invoke method`s together

im looking for the most efficient way to invoke couple of method
together.
Basically what im trying to to is invoke those method together and if something went wrong return error else return the struct Type.
This code is working but i can't get the struct type or error and im not sure if its the correct way.
go func()(struct,err) {
struct,err= sm.MethodA()//return struct type or error
err = sm.MethodB()//return error or nill
return struct,err
}()
In Go, it's idiomatic to return the two values and check for nil against the error
For example:
func myFunc(sm SomeStruct) (MyStruct, error) {
s, err := sm.MethodA()
if err != nil {
return nil, err
}
if err := sm.MethodB(); err != nil {
return nil, err
}
return s, nil
}
One thing to note, is that you're running your function in a goroutine. Any return value inside that goroutine won't be returned to your main goroutine.
In order to get the return values for that go routine you must use channels that will wait for the values.
In your case
errChan := make(chan error)
retChan := make(chan SomeStructType)
go func() {
myVal, err := sm.MethodA()
if err != nil {
errChan <- err
return
}
if err := sm.MethodB(); err != nil {
errChan <- err
return
}
retChan <- myVal
}()
select {
case err := <-errChan:
fmt.Println(err)
case val := <-retChan:
fmt.Printf("My value: %v\n", val)
}
You can mess around with it here to make more sense out of it:
http://play.golang.org/p/TtfFIZerhk

text/template issue Parse() vs. ParseFiles()

I'm trying to do some simple work with the text/template package. The sample given at the top of template is what I'm working with.
How do I write the 'parsed' file so template.ParseFiles() properly reads and executes it?
package main
import (
"text/template"
"os"
)
type Inventory struct {
Material string
Count uint
}
func main() {
sweaters := Inventory{"wool", 17}
tmpl, err := template.New("test").Parse("{{.Count}} items are made of {{.Material}}")
// tmpl, err := template.New("test").ParseFiles("file.txt")
if err != nil { panic(err) }
err = tmpl.Execute(os.Stdout, sweaters)
if err != nil { panic(err) }
}
/*
Contents of file.txt:
{{.Count}} items are made of {{.Material}}
Error thrown:
panic: template: test:1: "test" is an incomplete or empty template
goroutine 1 [running]:
main.main()
/tmp/templates/t.go:19 +0x21a
goroutine 2 [syscall]:
created by runtime.main
/var/tmp/portage/dev-lang/go-1.0.1/work/go/src/pkg/runtime/proc.c:221
*/
I have a copy of this code posted at the golang playground here
Edit #1:
I've been doing some research on this issue... since it's the Execute() method that actually throws the exception, and not the ParseFiles() part, I checked the method definition:
// Execute applies a parsed template to the specified data object,
// and writes the output to wr.
func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
defer errRecover(&err)
value := reflect.ValueOf(data)
state := &state{
tmpl: t,
wr: wr,
line: 1,
vars: []variable{{"$", value}},
}
if t.Tree == nil || t.Root == nil {
state.errorf("%q is an incomplete or empty template", t.name)
}
state.walk(value, t.Root)
return
}
So, on a hunch, I dumped the value of t.Tree for the inline 'non-file' style, tmpl is: &parse.Tree{Name:"test", Root:(*parse.ListNode)(0xf840030700), funcs:[]map[string]interface {}(nil), lex:(*parse.lexer)(nil), token:[2]parse.item{parse.item{typ:6, val:""}, parse.item{typ:9, val:"{{"}}, peekCount:1, vars:[]string(nil)} and
when ran with ParseFiles(), tmpl is: (*parse.Tree)(nil). I find it odd that one is a dereference, and one value is a pointer. This may help solve the riddle
sweaters := Inventory{"wool", 17}
tmpl, err := template.ParseFiles("file.txt")
if err != nil {
panic(err)
}
err = tmpl.ExecuteTemplate(os.Stdout, "file.txt", sweaters)
if err != nil {
panic(err)
}
If you have many files, you can use ParseGlob:
tmpl, err := template.ParseGlob("*.txt")
if err != nil {
panic(err)
}
err = tmpl.ExecuteTemplate(os.Stdout, "file.txt", sweaters)
if err != nil {
panic(err)
}
err = tmpl.ExecuteTemplate(os.Stdout, "file2.txt", sweaters)
if err != nil {
panic(err)
}
There is a little trick in Go template parseFiles.
func parseFiles(t *Template, filenames ...string) (*Template, error) {
if len(filenames) == 0 {
// Not really a problem, but be consistent.
return nil, fmt.Errorf("template: no files named in call to ParseFiles")
}
for _, filename := range filenames {
b, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
s := string(b)
name := filepath.Base(filename)
// First template becomes return value if not already defined,
// and we use that one for subsequent New calls to associate
// all the templates together. Also, if this file has the same name
// as t, this file becomes the contents of t, so
// t, err := New(name).Funcs(xxx).ParseFiles(name)
// works. Otherwise we create a new template associated with t.
var tmpl *Template
if t == nil {
t = New(name)
}
if name == t.Name() {
tmpl = t
} else {
tmpl = t.New(name)
}
_, err = tmpl.Parse(s)
if err != nil {
return nil, err
}
}
return t, nil
}
Only the template with same name will be reuse, otherwise create new one.
as your sample:
tmpl, err := template.New("test").ParseFiles("file.txt")
tmpl is the template named "test", and associated another template named "file.txt", you call Execute on "test" template, this template is a empty template, so raise the error "test is an incomplete or empty template".
It worked when you change the template name to file.txt
tmpl, err := template.New("file.txt").ParseFiles("file.txt")

Resources