Function override - function

I found something interesting in Go. Let's say I have my package name is mypkg, inside mypkg, I have two functions:
package mypkg
func MyFunc0(){
//...
}
var MyFunc1 = func(){
//...
}
Now in my main package, it is possible to override MyFunc1, like this:
mypkg.MyFunc1 = func(){
// new logic
}
However, it is not possible to override MyFunc0 the same way. So now a question is raised. What are the differences between the two ways of declaring a function? Is this behavior difference intended?

MyFunc0 is a function declaration (https://golang.org/ref/spec#Function_declarations)
MyFunc1 is not a function declaration. It is a variable (https://golang.org/ref/spec#Variable_declarations) of type func (see https://golang.org/ref/spec#Function_types, https://golang.org/ref/spec#Function_literals). It has an initial value, but can be changed to hold a different value/function (as long as function signatures match).

I learning go language (and English :P), and in the tour of go is a exersie: Fibonacci closure
(https://tour.golang.org/moretypes/22)
The result is:
0
1
1
2
3
5
8
13
21
34
The main function is:
func main() {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
}
And my first solution was:
func fibonacci() func() int {
antant := 0
ant := 1
i := 0
return func() int {
var result int
if i == 0 || i == 1 {
result = i
i++
return result
}
result = antant + ant
antant = ant
ant = result
return result
}
}
But I didn't want ask in heach call to f() if was the firsth or second call (if i == 0 || i == 1). The result was a function auto-override:
type doFibonacci func(*doFibonacci) int
func fibonacci() func() int {
antant := 0
ant := 1
i := 0
doFibo := doFibonacci(func(ptrDo *doFibonacci) int {
var result int
if i == 0 || i == 1 {
result = i
i++
return result
}
*ptrDo = func(ptrDo *doFibonacci) int {
var result int
result = antant + ant
antant = ant
ant = result
return result
}
return (*ptrDo)(ptrDo)
})
return func() int {
return doFibo(&doFibo)
}
}
I apologize for my English.

Related

Golang - How does golang memory profile count allocs/op?

I'm writing a custom JSON marshal function and comparing it to the built-in json.Marshal method.
My understanding is that when bytes.Buffer reaches its capacity, it needs to double its size and this costs 1 allocation.
However, benchmark result seems to indicate json.Marshal is doing this in a way where it does NOT need to allocate whenever it grows the underlying buffer, whereas my implementation seems to cost an extra allocation everytime the buffer doubles.
Why would MarshalCustom (code below) need to allocate more than json.Marshal?
$ go test -benchmem -run=^$ -bench ^BenchmarkMarshalText$ test
BenchmarkMarshalText/Marshal_JSON-10 79623 13545 ns/op 3123 B/op 2 allocs/op
BenchmarkMarshalText/Marshal_Custom-10 142296 8378 ns/op 12464 B/op 8 allocs/op
PASS
ok test 2.356s
Full code.
type fakeStruct struct {
Names []string `json:"names"`
}
var ResultBytes []byte
func BenchmarkMarshalText(b *testing.B) {
names := randomNames(1000)
b.Run("Marshal JSON", func(b *testing.B) {
fs := fakeStruct{
Names: names,
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
ResultBytes, _ = json.Marshal(fs)
}
})
b.Run("Marshal Custom", func(b *testing.B) {
fs := fakeStruct{
Names: names,
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
ResultBytes = MarshalCustom(fs)
}
})
}
func MarshalCustom(fs fakeStruct) []byte {
var b bytes.Buffer
b.WriteByte('{')
// Names
b.WriteString(`,"names":[`)
for i := 0; i < len(fs.Names); i++ {
if i > 0 {
b.WriteByte(',')
}
b.WriteByte('"')
b.WriteString(fs.Names[i])
b.WriteByte('"')
}
b.WriteByte(']')
b.WriteByte('}')
buf := append([]byte(nil), b.Bytes()...)
return buf
}
func randomNames(num int) []string {
const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
const maxLen = 5
rand.Seed(time.Now().UnixNano())
res := make([]string, rand.Intn(num))
for i := range res {
l := rand.Intn(maxLen) + 1 // cannot be empty
s := make([]byte, l)
for j := range s {
s[j] = letters[rand.Intn(len(letters))]
}
res[i] = string(s)
}
return res
}
#oakad is correct. If I force a GC run in every iteration of the benchmark, the allocs/op is much closer or even the same.
for i := 0; i < b.N; i++ {
// marshal here
runtime.GC()
}

defer - modify named return value vs non-named return value

Code
func deferModifyReturnValue() int {
x := 0
defer func() {
x += 1 // executed before return,
}()
return x
}
func deferModifyNamedReturnValue() (x int) {
defer func() {
x += 1 // executed before return,
}()
return
}
func TestDeferModifyReturnValue(t *testing.T) {
assert.Equal(t, 0, deferModifyReturnValue())
assert.Equal(t, 1, deferModifyNamedReturnValue())
}
Question
The test passes.
I can understand why the deferModifyNamedReturnValue() return 1, because defer modify it right before return.
But, how the deferModifyReturnValue() return 0? Does it make a copy to stack before the modification?

How to call a function inside another function in Go language?

I'm getting an error saying "undefined isvalid". How do I call another function in a function?
package main
import "fmt"
type Position struct {
row int
col int
}
func (posstn Position) isvalid() bool {
if posstn.row > 8 || posstn.row < 0 || posstn.col > 8 || posstn.col < 0 {
return false
}
return true
}
func Possmov(pos Position) {
var isval isvalid
if isval == true {
fmt.Println("Something")
}
}
func main() {
Possmov(Position{1, 7})
}
you may call isvalid() like this pos.isvalid() see this working sample code:
package main
import "fmt"
type Position struct {
row int
col int
}
func (posstn Position) isvalid() bool {
if posstn.row > 8 || posstn.row < 0 || posstn.col > 8 || posstn.col < 0 {
return false
}
return true
}
func Possmov(pos Position) {
isval := pos.isvalid()
if isval == true {
fmt.Println("Something")
}
}
func main() {
Possmov(Position{1, 7}) //Something
}
Your first line in function Possmov(pos Position){...} i.e. var isval isvalid is actually attempting to declare a variable of type isvalid (which is undefined as described by the error)
Instead your isvalid() method is declared on the Position type.
Try: var isvalid = pos.isvalid() in it's place
Your defined var isval isvalid, while isvalid is not a known type in Go, instead:
func Possmov(pos Position) {
var isval bool // default is false
if isval == true {
fmt.Println("Something")
}
}
https://play.golang.org/p/Ml2PgEOZfV

How do I access a method expression (struct function) from within another method expression in Go / Golang?

I am trying to clean up the code in a Go / Golang project of mine. I thought that it might be idiomatic to create a model in an object-oriented way such that I can do, for example:
db.Users.GetID("john") (to do a thing in the "users" table)
db.Purchases.GetTotal() (to do a thing in the "purchasaes" table)
Etc. However, one problem with this is this is that the database functions can't call themselves if they need to.
Here's a tiny, contrived example of what I am talking about:
package main
import "fmt"
// A model that contains all of the structs for our database tables
type Model struct {
Users
Purchases
}
// A struct for functions that have to do with the "users" table
type Users struct {}
func (self *Users) Exists(id int) bool {
// Check to see if the user exists
// SELECT id FROM users WHERE id = ?
return true // (omitted)
}
// A struct for functions that have to do with the "purchases" table
type Purchases struct {}
func (self *Purchases) Count(id int) int {
// First validate that the user exists
if db.Users.Exists(id) == false { // This fails <--------------
return 0
} else {
// Get the count of that user's purchases
// SELECT COUNT(user_id) FROM purchases WHERE user_id = ?
return 50 // (omitted)
}
}
func main() {
db := Model{}
numPurchases := db.Purchases.Count(123)
if numPurchases != 0 {
fmt.Println("User #123 has", numPurchases, "purchases!")
} else {
fmt.Println("User #123 does not exist!")
}
}
This results in an error:
undefined: db in db.Users
If I changed it to just Users.Exists instead of db.Users.Exists:
./test.go:22: invalid method expression Users.Exists (needs pointer receiver: (*Users).Exists)
./test.go:22: Users.Exists undefined (type Users has no method Exists)
Note that, in this contrived example, it is pointless to be validating that the user exists. However, the point is that a DB function should have the ability to call some other DB function in case there is something actually important to validate.
How can I accomplish / work around this?
(Edit - Modified the code snippet for clarity.)
What you are trying to do is not possible in Go. Users.Exists is a Method Expression. With these, you can take a method and convert it into a simple function type.
userExists := Users.Exists
user := User{}
// now userExists can be called as a regular function with
// first argument of a Users type
exists := userExists(&user, id)
As a result you cannot structure your model exactly like you have mentioned above.
Go is not a completely Object Oriented language and you should not try to replicate strictly OOP structures and idioms in it. In your case above, if you need an Exists function, you can always move Users into a separate package and define Exists as a function:
package user
type Users struct {}
// other methods on Users type
func Exists(id int) bool {
// check to see if user exists
}
You can now make the following calls:
import "user"
user.Exists(id)
After you initialize the struct, you can fill it with self references. Since I am new to Go, I'm not sure if it is considered idiomatic, but it seems to work just just fine.
The fixed code snippet:
package main
import "fmt"
// A model that contains all of the structs for our database tables
type Model struct {
Users
Purchases
}
// A struct for functions that have to do with the "users" table
type Users struct {
db *Model
}
func (self *Users) Exists(id int) bool {
// Check to see if the user exists
// SELECT id FROM users WHERE id = ?
return true // (omitted)
}
// A struct for functions that have to do with the "purchases" table
type Purchases struct {
db *Model
}
func (self *Purchases) Count(id int) int {
// First validate that the user exists
if self.db.Users.Exists(id) == false { // This succeeds now <--------------
return 0
} else {
// Get the count of that user's purchases
// SELECT COUNT(user_id) FROM purchases WHERE user_id = ?
return 50 // (omitted)
}
}
func main() {
// Initialize the model and fill it with helpful self-references
db := Model{}
db.Users.db = &db
db.Purchases.db = &db
// In practice, you will want to do this in some sort of custom constructor, like:
// var db Model*
// db := Model.NewModel(db)
numPurchases := db.Purchases.Count(123)
if numPurchases != 0 {
fmt.Println("User #123 has", numPurchases, "purchases!")
} else {
fmt.Println("User #123 does not exist!")
}
}
if you need field inside Users struct, you may use like db.Exists(2) or even Users.Exists(db, 2) both are valid. like this working sample code:
package main
import "fmt"
type Users struct {
Ids []int
}
func (t Users) Exists(id int) bool {
for _, v := range t.Ids {
if v == id {
return true
}
}
return false
}
func main() {
db := Users{[]int{1, 2}}
r1 := db.Exists(2)
r2 := Users.Exists(db, 2)
fmt.Println(r1, r2) // true true
}
you may use it like db.Exists(2) or even Users.Exists(db, 2)
both are valid. you may use Users struct just for grouping methods, like this working sample code:
package main
import "fmt"
type Users struct{}
var Ids = []int{1, 2}
func (t Users) Exists(id int) bool {
for _, v := range Ids {
if v == id {
return true
}
}
return false
}
func main() {
db := Users{}
r1 := db.Exists(2)
r2 := Users.Exists(db, 2)
fmt.Println(r1, r2) // true true
}
you may use UserExists(2) when you do not need grouping, like this working sample code:
package main
import "fmt"
type Users struct{}
var Ids = []int{1, 2}
func UserExists(id int) bool {
for _, v := range Ids {
if v == id {
return true
}
}
return false
}
func main() {
r1 := UserExists(2)
fmt.Println(r1) // true
}
so in your case this works fine:
package main
import "fmt"
type Model struct {
Users
Purchases
}
type Users struct{}
var users Users
func (*Users) Exists(id int) bool {
return true
}
type Purchases struct{}
func (*Purchases) Count(id int) int {
if users.Exists(id) == false {
return 0
} else {
return 50
}
}
func main() {
db := Model{}
numPurchases := db.Purchases.Count(123)
if numPurchases != 0 {
fmt.Println("User #123 has", numPurchases, "purchases!")
}
}
output:
User #123 has 50 purchases!

How can I create a JSON structure dynamically from Go?

As in, serializing JSON.
My current code doesn't work, and I think it must have something to do with the fact that _Map, _String, etc. are not public.
// vim:ft=go:ts=2
package main
import "json"
import "fmt"
import vector "container/vector"
func main() {
groceries := vector.New(0);
groceries.Push(&json._String{s:"Eggs"});
groceries.Push(&json._String{s:"Bread"});
groceries.Push(&json._String{s:"Milk"});
var tree json.Json = &json._Map{m:map[string]json.Json{
"hello": &json._String{s:"world"},
"groceries": &json._Array{a:groceries}
}};
fmt.Printf(json.JsonToString(tree));
}
Have a look at the TestJsonMap function in $GOROOT/src/pkg/json/generic_test.go, it seems to do something similar to what you want. The relevant code is
var jsontests = []string{
`null`,
`true`,
`false`,
`"abc"` // , etc.
}
values := make(map[string]Json);
mapstr := "{";
for i := 0; i < len(jsontests); i++ {
val, ok, errtok := StringToJson(jsontests[i]);
if !ok {
t.Errorf("StringToJson(%#q) => error near %v", jsontests[i], errtok)
}
if i > 0 {
mapstr += ","
}
values[jsontests[i]] = val;
mapstr += Quote(jsontests[i]);
mapstr += ":";
mapstr += JsonToString(val);
}
mapstr += "}";
mapv, ok, errtok := StringToJson(mapstr);
You want to push the value "world" onto the name "hello" and ["Eggs","Bread","Milk"] onto "Groceries". Try
var values = make(map[string]string);
values["hello"] = `"world"`;
values["groceries"] = `["Eggs","Bread","Milk"]`;
mapstr := "{";
needcomma := false;
for key,val := range values {
jsonval, ok, errtok := json.StringToJson(val);
// Check errors
// Add a comma
if needcomma == true {
mapstr += ",";
} else {
needcomma = true;
}
mapstr += json.Quote(key);
mapstr += ":";
mapstr += json.JsonToString(jsonval);
}
mapstr += "}";
mapv, ok, errtok := json.StringToJson(mapstr);
Here is the bare bones of an implementation of the interface for Json:
package main
import {"json"; "fmt"; "os";}
type MyTest struct { MyMap map[string]string;}
func (t * MyTest) Kind() int { return json.MapKind }
func (t * MyTest) Len() int { return len (t.MyMap) }
func (t * MyTest) Number() float64 { return 0 }
func (t * MyTest) Bool() bool { return false }
func (t * MyTest) Elem(int) json.Json { return json.Null }
func (t * MyTest) String() (s string) {
s = "{";
count := 0;
for key, value := range t.MyMap {
s += json.Quote(key) + ":" + json.Quote(value);
count++;
if (count < len (t.MyMap)) {
s += ",";
}
}
s += "}";
return;
}
func (t * MyTest) Get(s string) json.Json {
j, ok, errtok := json.StringToJson (t.MyMap[s]);
if ! ok {
fmt.Printf ("Fail at %s\n", errtok);
os.Exit (1);
}
return j;
}
Here is some testing code:
func main () {
var megaburger = new (MyTest);
megaburger.MyMap = make(map[string]string);
megaburger.MyMap["frog"] = "toad";
megaburger.MyMap["captain"] = "kirk";
megaburger.MyMap["laser"] = "phaser";
fmt.Println (megaburger.Kind());
fmt.Println (megaburger.Len());
fmt.Println (json.JsonToString (megaburger));
}
This puts a JsonToString method onto the type MyTest by defining the interface for the Json package. Clearly this doesn't do anything interesting yet, but you could define various things like these for your particular data structure in order to have a "JSON-izer" which created whatever JSON you liked from your structure. There is a nice example of how to do embedding using something called _Null in the library source code file generic.go.
This looks promising.
//import "github.com/Jeffail/gabs"
jsonObj := gabs.New()
// or gabs.Consume(jsonObject) to work on an existing map[string]interface{}
jsonObj.Set(10, "outter", "inner", "value")
jsonObj.SetP(20, "outter.inner.value2")
jsonObj.Set(30, "outter", "inner2", "value3")
fmt.Println(jsonObj.String())
// Prints
// {"outter":{"inner":{"value":10,"value2":20},"inner2":{"value3":30}}}