title: Go

#+STARTUP: overview

Go Features

Note

Array

  • Array & Slice: Array must with specialized length for [x]
  • function:
    • must given specialized arguments(if point) when execution
  • method:
    • Must have a receiver
    • if receiver is pointer of instance, the value of instance can be modified
    • for execution: the instance of receiver can be pointer or not, will automatically convered
    • if receiver is not a pointer, the receiver can still be a pointer

interface

  • def interface with its contains
  • def receiver
  • receiver implementing the contains with methods(just like method above)
  • instancing of interface
  • instancing of receiver
  • passing receiver to interface(if the implementation is kind of pointer for receiver, here also pass pointer)
  • executing methods of interface

Slice

As you've noticed, when you slice from the end, it's the length that shrinks. The pointer to the first element and the capacity remain unchanged.

When you slice from the beginning of the slice, though, what happens instead is the pointer to the first element is changed to be a pointer to the nth element that you're slicing from (i.e. sl = arr[2:] means to set the pointer to point to &arr[2]). Because the head of the slice has moved forward 2, in this case, the length and capacity have to decrease by 2.

Generics

package main
import "fmt"
func Sum[V int64 | float64](m ...V) V {
        var s V
        for _,v := range m {
                s += v
        }
        return s
}
func main() {
        fmt.Println(Sum([]int64{1,2,3,4,5}...))
        fmt.Println(Sum(int64(1),int64(2),int64(3),int64(4)))
        fmt.Println(Sum(1.1, 2.2, 3.3, 4.4))
}  
package main
import (
        "fmt"
        "golang.org/x/exp/constraints"
)
func Sum[V constraints.Float | constraints.Integer](m ...V) V {
        var s V
        for _,v := range m {
                s += v
        }
        return s
}
func main() {
        fmt.Println(Sum([]int64{1,2,3,4,5}...))
        fmt.Println(Sum(1,2,3,4))
        fmt.Println(Sum(1.1, 2.2, 3.3, 4.4))
        fmt.Println(Sum(uint32(2), uint32(4)))
}  
cd babel
go mod init go-generics-constraints
go mod tidy
go build go_generics_constraints.go
rm main.go
rm go.mod
rm go.sum
./go_generics_constraints
15
10
11
6

Strings

package main
import (
        "fmt"
        "strings"
)
func main() {
        cut := func(sep string) {
                s:= "hello|world"
                before, after, found := strings.Cut(s, sep)
                fmt.Printf("Cut(%q, %q): %q, %q, %v\n", s, sep, before, after, found)
        }
        cut("|")
        cut("hello")
        cut("nothing")
}
Cut("hello|world", "|"): "hello", "world", true
Cut("hello|world", "hello"): "", "|world", true
Cut("hello|world", "nothing"): "hello|world", "", false

Array

package main
import (
        "fmt"
)
func test(array []int64) {
        for i:= 0; i< 3; i++{
                array[i] = 10
        }
}

func main() {
        start := make([]int64, 3)
        test(start)
        fmt.Println(start)
}



[10 10 10]

Map

three way to create a map

package main
import (
        "fmt"
)
func main() {
        myMap1 := make(map[string]string, 10)
        fmt.Println(myMap1)
        myMap1["one"] = "python"
        fmt.Println(myMap1)
        myMap2 := make(map[string]string)
        myMap2["one"] = "python"
        fmt.Println(myMap2)          
        myMap3 := map[string]string{
                "one": "python",
        }
        fmt.Println(myMap3)
}
map[]
map[one:python]
map[one:python]
map[one:python]

Methode

function(copy or pointer) methode(copy or pointer)

interface

package main
import (
        "fmt"
)
type AnimalIF interface{
        Sleep()
        GetColor() string
        GetType() string
}

type Cat struct{
        color string
}

func (this *Cat) Sleep(){
        fmt.Println("Cat is sleeping")
}
func (this *Cat) GetColor() string {
        return this.color
}
func (this *Cat) GetType() string {
        return "Cat"
}

type Dog struct{
        color string
}

func (this *Dog) Sleep(){
        fmt.Println("Dog is sleeping")
}
func (this *Dog) GetColor() string {
        return this.color
}
func (this *Dog) GetType() string {
        return "Dog"
}
func ShowInfo(animal AnimalIF){
        animal.Sleep()
        fmt.Println("color = ", animal.GetColor())
        fmt.Println("type = ", animal.GetType())
}

func main() {
        cat := Cat{"Green"}
        dog := Dog{"Yellow"}
        ShowInfo(&cat)
        ShowInfo(&dog)
}
Cat is sleeping
color =  Green
type =  Cat
Dog is sleeping
color =  Yellow
type =  Dog

interface {} assert: arg.(string), if arg is not {}, it will be forced to convert to string can refer to every kind of value

polymorphism

OpenFile already implemented Wirter and Reader

package main

import (
    "fmt"
    "io"
    "os"
)

func main() {
    tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
    if err != nil {
        fmt.Println("Open file with error", err)
        return
    }
    var r io.Reader
    r = tty
    var w io.Writer
    w = r.(io.Writer)
    w.Write([]byte("HELLO from meb\n"))
}


Open file with error open /dev/tty: no such device or address

reflect

package main

import (
        "fmt"
        "reflect"
)

func reflectNum(arg interface{}){
        fmt.Println("type: ", reflect.TypeOf(arg))
        fmt.Println("value: ", reflect.ValueOf(arg))
}

func main(){
        var num float64 = 3.1415926
        reflectNum(num)
}

type:  float64
value:  3.1415926
package main
import (
        "fmt"
        "reflect"
)

type User struct {
        Id int
        Name string
        Age int
}

func (this User) Call(){
        fmt.Println("user is calling")
        fmt.Printf("%v\n", this)
}

func (this User) End_Call(id int){
        fmt.Println(id)
        fmt.Printf("%v\n", this)
}

func main(){
        user := User{10, "Alice", 23}
        reflectExample(user)
}

func reflectExample(input interface{}){
        //get tpye
        inputType := reflect.TypeOf(input)
        fmt.Println("input Type is :", inputType.Name())


        //get value
        inputValue := reflect.ValueOf(input)
        fmt.Println("value Type is :", inputValue)


        //get fields in details
        for i := 0; i< inputType.NumField(); i++ {
                field := inputType.Field(i)
                value := inputValue.Field(i).Interface()
                fmt.Printf("%s: %v = %v\n",field.Name, field.Type, value)
        }

        //get methods in details
        for i := 0; i< inputType.NumMethod(); i++ {
                method := inputType.Method(i)
                fmt.Printf("%s: %v\n", method.Name, method.Type)
        }
}
input Type is : User
value Type is : {10 Alice 23}
Id: int = 10
Name: string = Alice
Age: int = 23
Call: func(main.User)
End_Call: func(main.User, int)

time

package main
import (
    "fmt"
    "time"
)
func test() {
    start := time.Now()
    sum := 0
    for i := 0; i < 100000; i++ {
        sum++
    }
    elapsed := time.Since(start)
    fmt.Println("该函数执行完成耗时:", elapsed)
}

func main() {
    test()
}

该函数执行完成耗时: 33.536µs

sync

package main

import "fmt"

func produce(c chan<- int) {
    for i := 0; i < 10; i++ {
        fmt.Printf(" Produced : %d\n", i)
        c <- i // synchronization
    }
}

func consume(c <-chan int) {
    for true {
        i := <-c // synchronization
        fmt.Printf(" Consumed : %d\n", i)
    }
}

func main() {
    c := make(chan int)
    go consume(c)
    produce(c)
}
Produced : 0
 Consumed : 0
 Produced : 1
 Produced : 2
 Consumed : 1
 Consumed : 2
 Produced : 3
 Produced : 4
 Consumed : 3
 Consumed : 4
 Produced : 5
 Produced : 6
 Consumed : 5
 Consumed : 6
 Produced : 7
 Produced : 8
 Consumed : 7
 Consumed : 8
 Produced : 9
package main
import (
    "fmt"
    "time"
    "sync"
)
func main() {
    var wg sync.WaitGroup
    wg.Add(1)

    go func(){
        count("Sleep")
        wg.Done()
    }()
    wg.Wait()
}

func count(thing string) {
    for i := 1; i <= 5; i++ {
        fmt.Println(i, thing)
        time.Sleep(time.Millisecond*500)
    }

}
1 Sleep
2 Sleep
3 Sleep
4 Sleep
5 Sleep

go

package main
import (
    "fmt"
    "time"
)
func main() {
    var times int
    go func() {
        for {
        }
    }()
    go func() {
        for {
        }
    }()
    go func() {
        for {
        }
    }()
    go func() {
        for {
        }
    }()
    for times = 0; times <= 10; times++ {
        fmt.Println("tick", times)
        time.Sleep(time.Second)
    }
}

tick 0
tick 1
tick 2
tick 3
tick 4
tick 5
tick 6
tick 7
tick 8
tick 9
tick 10

chan

example

package main
import "fmt"
func main() {
    // 创建一个整型带两个缓冲的通道
    ch := make(chan int, 2)

    // 给通道放入两个数据
    ch <- 0
    ch <- 1

    // 关闭缓冲
    close(ch)
    // 遍历缓冲所有数据, 且多遍历1个
    for i := 0; i < cap(ch)+1; i++ {

        // 从通道中取出数据
        v, ok := <-ch

        // 打印取出数据的状态
        fmt.Println(v, ok)
    }
}
#+RESULTS:

dead lock unbuffer channel

package main
import "fmt"
func main() {
    // 创建一个整型带两个缓冲的通道
    ch := make(chan int)

    // 给通道放入两个数据
    ch <- 0
    id := <- ch
    fmt.Println(id)

    close(ch)
}

*but can be saved with goroutine*

package main
import "fmt"
func main() {
    ch := make(chan int)
    go func(){
      ch <- 0
    }()
    id := <- ch
    fmt.Println(id)
    close(ch)
}
0

deal lock after buffer channel is full

buffer can be filled

package main
import "fmt"
func main() {
    ch := make(chan int, 2)

    ch <- 0
    ch <- 1
    id := <- ch
    fmt.Println(id)

    close(ch)
}
0

but can not be exceeded

package main
import "fmt"
func main() {
    ch := make(chan int, 2)

    ch <- 0
    ch <- 1
    ch <- 2
    id := <- ch
    fmt.Println(id)

    close(ch)
}
0

context

package main

import (
    "fmt"
    "context"
    "time"
)

func enrichContext(ctx context.Context) context.Context {
    return context.WithValue(ctx, "request-id", "11212")

}

func doSomething(ctx context.Context){
    rID := ctx.Value("request-id")
    fmt.Println(rID)
    for {
        select {
        case <-ctx.Done():
            fmt.Println("times out")
            return
        default:
            fmt.Println("doing something cool")
        }
        time.Sleep(500*time.Millisecond)
    }
}


func main (){
    fmt.Println("Go Context example")
    ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
    defer cancel()
    fmt.Println(ctx.Err())
    ctx = enrichContext(ctx)
    go doSomething(ctx)
    select {
    case <- ctx.Done():
        fmt.Println("Oh, no, Time is execeed the deadline")
        fmt.Println(ctx.Err())
    }
    time.Sleep(2*time.Second)
}
Go Context example
<nil>
11212
doing something cool
doing something cool
doing something cool
doing something cool
Oh, no, Time is execeed the deadline
context deadline exceeded
times out
package main

import (
    "context"
    "fmt"
    "log"
    "time"
)

func main() {
    start := time.Now
    ctx := context.Background()
    userId := 10
    val, err := fetchUserData(ctx, userId)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("result : ", val)
    fmt.Println("took ", time.Since(start()))
}

type Response struct {
    value int
    err   error
}

func fetchUserData(ctx context.Context, userid int) (int, error) {
    ctx, cancel := context.WithTimeout(ctx, time.Millisecond*200)
    defer cancel()

    respch := make(chan Response)

    go func() {
        val, err := fetchThirdPartyStuffWhichCanbeSlow()
        respch <- Response{
            value: val,
            err:   err,
        }
    }()

    for {
        select {
        case <-ctx.Done():
            return 0, fmt.Errorf("Fetch data is time out")
        case resp := <-respch:
            return resp.value, resp.err
        }
    }
}

func fetchThirdPartyStuffWhichCanbeSlow() (int, error) {
    time.Sleep(time.Millisecond * 150)
    return 666, nil
}

gonum

Test example

package main

import (
        "fmt"

        "gonum.org/v1/gonum/blas/blas64"
        "gonum.org/v1/gonum/mat"
)

func main() {
        r := row{1, 2, 3, 4}
        c := column{1, 2, 3}

        var m mat.Dense
        m.Mul(c, r)

        fmt.Println(mat.Formatted(&m))
        n := c.RawVector().N
        inc := c.RawVector().Inc
        d := c.RawVector().Data
        fmt.Println(n)
        fmt.Println(inc)
        fmt.Println(d)

        u := mat.NewVecDense(3, []float64{1, 2, 3})
        v := mat.NewVecDense(3, []float64{4, 5, 6})
        fmt.Println("u :", u)
        fmt.Println("v :", v)

}

// row is a user-defined row vector.
type row []float64

// Dims, At and T minimally satisfy the mat.Matrix interface.
func (v row) Dims() (r, c int)    { return 1, len(v) }
func (v row) At(_, j int) float64 { return v[j] }
func (v row) T() mat.Matrix       { return column(v) }

// RawVector allows fast path computation with the vector.
func (v row) RawVector() blas64.Vector {
        return blas64.Vector{N: len(v), Data: v, Inc: 1}
}

// column is a user-defined column vector.
type column []float64

// Dims, At and T minimally satisfy the mat.Matrix interface.
func (v column) Dims() (r, c int)    { return len(v), 1 }
func (v column) At(i, _ int) float64 { return v[i] }
func (v column) T() mat.Matrix       { return row(v) }

// RawVector allows fast path computation with the vector.
func (v column) RawVector() blas64.Vector {
        return blas64.Vector{N: len(v), Data: v, Inc: 1}
}

NewDense

package main

import (
        "fmt"
        "gonum.org/v1/gonum/mat"
)

func main() {
        zeros := mat.NewDense(3,5,nil)
        fmt.Println(zeros)
}

make

package main

import (
        "fmt"
        "math/rand"
        "gonum.org/v1/gonum/mat"
)

func main() {
        data := make([]float64, 36)
        for i := range data {
                data[i] = rand.NormFloat64()
        }
        a := mat.NewDense(6, 6, data)
        zeros := mat.NewDense(3,5,nil)
        // fmt.Println(mat.Formatted(zeros, mat.Prefix(""), mat.Squeeze()))
        // fmt.Println(mat.Formatted(a, mat.Prefix(""), mat.Squeeze()))
        eq := mat.Equal(a, zeros)
        fmt.Println(eq)

}

gonum execute

cd babel
go mod init babel-go
go mod tidy
go build main.go
rm main.go
rm go.mod
rm go.sum
./main
false

PatternDesign

Observer

package main

import (
        "fmt"
        "sync"
        "time"
)

type (
        eventObserver struct {
                id   int
                time time.Time
        }
        eventSubject struct {
                observers sync.Map
        }
        Event struct {
                data int
        }
        Observer interface {
                NotifyCallback(Event)
        }
        Subject interface {
                AddListener(Observer)
                RemoveListener(Observer)
                Notify(Event)
        }
)

// NotifyCallback ...
func (e *eventObserver) NotifyCallback(event Event) {
        fmt.Printf("Observer: %d Recieved: %d after %v\n", e.id, event.data, time.Since(e.time))
}

// AddListener ...
func (s *eventSubject) AddListener(obs Observer) {
        s.observers.Store(obs, struct{}{})
}

// RemoveListener ...
func (s *eventSubject) RemoveListener(obs Observer) {
        s.observers.Delete(obs)
}

// Notify  ...
func (s *eventSubject) Notify(event Event) {
        s.observers.Range(func(key interface{}, value interface{}) bool {
                fmt.Printf("%T", key)
                if key == nil || value == nil {
                        return false
                }
                key.(Observer).NotifyCallback(event)
                return true
        })
}

func fib(n int) chan int {
        out := make(chan int)
        go // name ...
        func() {
                defer close(out)
                for i, j := 0, 1; i < n; i, j = i+j, i {
                        out <- i
                }
        }()
        return out
}

func main() {
        n := eventSubject{
                observers: sync.Map{},
        }
        var obs1 = eventObserver{id: 1, time: time.Now()}
        var obs2 = eventObserver{id: 2, time: time.Now()}

        n.AddListener(&obs1)
        n.AddListener(&obs2)
        n.AddListener(&eventObserver{id: 3, time: time.Now()})

        go func() {
                select {
                case <-time.After(time.Millisecond):
                        n.RemoveListener(&obs2)
                }
        }()

        for x := range fib(1000000000000000000) {
                n.Notify(Event{data: x})
        }
}

Factory

package main

import (
        "fmt"
        "reflect"
)

type (
        mongoDB struct {
                database map[string]string
        }
        sqlite struct {
                database map[string]string
        }
        Database interface {
                GetData(string) string
                PutData(string, string)
        }
        file struct {
                name    string
                content string
        }
        ntfs struct {
                files map[string]file
        }
        ext4 struct {
                files map[string]file
        }
        FileSystem interface {
                CreateFile(string)
                FindFile(string) file
        }

        Factory func(string) interface{}
)

func (mdb mongoDB) GetData(query string) string {
        if _, ok := mdb.database[query]; !ok {
                return ""
        }
        fmt.Println("MongoDB")
        return mdb.database[query]
}

func (mdb mongoDB) PutData(query string, data string) {
        mdb.database[query] = data
}

func (sql sqlite) GetData(query string) string {
        if _, ok := sql.database[query]; !ok {
                return ""
        }
        fmt.Println("Sqlite")
        return sql.database[query]
}

func (sql sqlite) PutData(query string, data string) {
        sql.database[query] = data
}

func (ntfs ntfs) CreateFile(path string) {
        file := file{content: "NTFS file", name: path}
        ntfs.files[path] = file
        fmt.Println("NTFS")
}

func (ext ext4) CreateFile(path string) {
        file := file{content: "EXT4 file", name: path}
        ext.files[path] = file
        fmt.Println("EXT4")
}

func (ntfs ntfs) FindFile(path string) file {
        if _, ok := ntfs.files[path]; !ok {
                return file{}
        }
        return ntfs.files[path]
}

func (ext ext4) FindFile(path string) file {
        if _, ok := ext.files[path]; !ok {
                return file{}
        }
        return ext.files[path]
}

// DatabaseFactory ...
func DatabaseFactory(env string) interface{} {
        switch env {
        case "production":
                return mongoDB{
                        database: make(map[string]string),
                }
        case "development":
                return sqlite{
                        database: make(map[string]string),
                }
        default:
                return nil
        }
}

func FilesystemFactory(env string) interface{} {
        switch env {
        case "production":
                return ntfs{
                        files: make(map[string]file),
                }
        case "development":
                return ext4{
                        files: make(map[string]file),
                }
        default:
                return nil
        }
}

// AbstractFactoryy ...
func AbstractFactory(fact string) func(string) interface{} {
        switch fact {
        case "database":
                return DatabaseFactory
        case "filesystem":
                return FilesystemFactory
        default:
                return nil
        }
}

func SetupConstructors(env string) (Database, FileSystem) {
        fs := AbstractFactory("filesystem")
        db := AbstractFactory("database")
        return db(env).(Database), fs(env).(FileSystem)

}

func main() {
        env1 := "production"
        env2 := "development"

        // db1 := DatabaseFactory(env1)
        // db2 := DatabaseFactory(env2)

        db1, fs1 := SetupConstructors(env1)
        db2, fs2 := SetupConstructors(env2)

        db1.PutData("test", "for test")
        fmt.Println(db1.GetData("test"))
        db2.PutData("test2", "for test2")
        fmt.Println(db2.GetData("test2"))

        fs1.CreateFile("../example/fts.txt")
        fmt.Println(fs1.FindFile("../example/fts.txt"))

        fs2.CreateFile("../example/et4.txt")
        fmt.Println(fs2.FindFile("../example/et4.txt"))

        fmt.Println(reflect.TypeOf(db1).Name())
        fmt.Println(reflect.TypeOf(&db1).Elem())
        fmt.Println(reflect.TypeOf(db2).Name())
        fmt.Println(reflect.TypeOf(&db2).Elem())

        fmt.Println(reflect.TypeOf(fs1).Name())
        fmt.Println(reflect.TypeOf(&fs1).Elem())
        fmt.Println(reflect.TypeOf(fs2).Name())
        fmt.Println(reflect.TypeOf(&fs2).Elem())
}

MongoDB
for test
Sqlite
for test2
NTFS
{../example/fts.txt NTFS file}
EXT4
{../example/et4.txt EXT4 file}
mongoDB
main.Database
sqlite
main.Database
ntfs
main.FileSystem
ext4
main.FileSystem

Decorator

package main

import (
        "fmt"
        "log"
        "math"
        "os"
        "sync"
        "time"
)

func Pi(n int) float64 {
        ch := make(chan float64)
        for k := 0; k <= n; k++ {
                go func(ch chan float64, k float64) {
                        ch <- 4 * math.Pow(-1, k) / (2*k + 1)
                }(ch, float64(k))
        }
        result := 0.0
        for k := 0; k <= n; k++ {
                result += <-ch
        }
        return result
}

type piFunc func(int) float64

func wraplogger(fun piFunc, logger *log.Logger) piFunc {
        return func(n int) float64 {
                fn := func(n int) (result float64) {
                        defer func(t time.Time) {
                                logger.Printf("took=%v, v=%v, result=%v", time.Since(t), n, result)
                        }(time.Now())
                        return fun(n)
                }
                return fn(n)
        }
}

func wrapcache(fun piFunc, cache *sync.Map) piFunc {
        return func(n int) float64 {
                fn := func(n int) float64 {
                        key := fmt.Sprintf("n=%d", n)
                        val, ok := cache.Load(key)
                        if ok {
                                return val.(float64)
                        }
                        result := fun(n)
                        cache.Store(key, result)
                        return result
                }
                return fn(n)
        }
}

func divide(n int) float64 {
        return float64(n / 2)
}

func main() {
        // 01
        // fmt.Println(Pi(1000))
        // fmt.Println(Pi(50000))
        // 02
        //f := wraplogger(Pi, log.New(os.Stdout, "test", 1))
        // f(10000)
        //03
        f := wrapcache(Pi, &sync.Map{})
        g := wraplogger(f, log.New(os.Stdout, "test", 1))
        g(100000)
        g(200000)
        g(500000)
        g(500000)
        // 04
        f = wrapcache(divide, &sync.Map{})
        g = wraplogger(f, log.New(os.Stdout, "divide", 1))
        g(100000)
        g(200000)
        g(500000)
        g(500000)
}


test2022/07/12 took=197.241951ms, v=100000, result=3.1416026534897195
test2022/07/12 took=326.435601ms, v=200000, result=3.1415976535647596
test2022/07/12 took=678.005443ms, v=500000, result=3.1415946535856927
test2022/07/12 took=2.673µs, v=500000, result=3.1415946535856927
divide2022/07/12 took=15.404µs, v=100000, result=50000
divide2022/07/12 took=3.475µs, v=200000, result=100000
divide2022/07/12 took=1.724µs, v=500000, result=250000
divide2022/07/12 took=922ns, v=500000, result=250000

单例模式

package main

import (
        "fmt"
)

type User struct {
        Name       string
        Occupation string
}


type Moli interface {
        Changename()
        ChangeOccupation()
}

func  CreateUser() (Moli,  *User){
        var moli Moli
        u := new(User)
        moli = u
        return moli, u
}

func (u *User) Changename (){
        u.Name = "Joke"
}


func (u *User) ChangeOccupation (){
        u.Occupation = "driver"
}


func changeName(u User) {
        u.Name = "Newi"
}


func changeOccupation(u User) {
        u.Occupation = "driver"
}

func main() {
        M, user := CreateUser()
        fmt.Println("should be empty", user)

        user.Name = "kji"
        fmt.Println("Directly can change the name", *user)

        user.Occupation = "Nothing"
        fmt.Println("Directly can change the occupation", *user)

        changeName(*user)
        fmt.Println("In function, indieictly can not be changed", *user)

        changeOccupation (*user)
        fmt.Println("In function, idieictly can not be changed", *user)

        M.Changename()
        fmt.Println("In methode, indieictly can be changed its name", *user)

        M.ChangeOccupation()
        fmt.Println("In methode,  indieictly can be changed its occupation", *user)

}

should be empty &{ }
Directly can change the name {kji }
Directly can change the occupation {kji Nothing}
In function, indieictly can not be changed {kji Nothing}
In function, idieictly can not be changed {kji Nothing}
In methode, indieictly can be changed its name {Joke Nothing}
In methode,  indieictly can be changed its occupation {Joke driver}

Architecture

package

each folder can only has one named package, but it can be shared for many files, also for the test file

module

it is the same designed as project, but only without main function and main package. it can be used by local package, module or project, but has to be replaced

go mod edit -replace modulename=folder  
  • modul name is defined in the go.mod file, and also at last one package should named as it
  • floder can be relative path, or absolute path in the reference package, module or project.
  • can be called from gore, but first :import

project

  • the same with module, with main package and main func, can be call as go run xxx.go
  • can not be called from gore for now (29.07.2022)

here is also1 here is also2 here is also3 here is also4

pprof, allow cpu and mem profile

  import (
        "os"
        "time"

        "github.com/pkg/profile"
        "runtime/pprof"
)

  cpuFile, _ := os.Create("cpu.pprof")
  pprof.StartCPUProfile(cpuFile)
  defer pprof.StopCPUProfile()

  defer profile.Start(profile.MemProfile, profile.ProfilePath(".")).Stop()