Showing posts with label golang_code. Show all posts
Showing posts with label golang_code. Show all posts

Sep 2, 2019

[Go][tricks] API compatibility

Reference:
GopherCon 2019: Jonathan Amsterdam - Detecting Incompatible API Changes
https://www.youtube.com/watch?v=JhdL5AkH-AQ
Slides:
https://about.sourcegraph.com/go/gophercon-2019-detecting-incompatible-api-changes
Spec:
https://go.googlesource.com/exp/+/refs/heads/master/apidiff/README.md
Tools binary:
$ go get golang.org/x/exp/cmd/apidiff  # will be replaced by gorelease
Golang /x/tools/go/packages
https://godoc.org/golang.org/x/tools/go/packages
Golang types package
https://golang.org/pkg/go/types/
Golang constant package
https://golang.org/pkg/go/constant/
Golang gcexportdata package
https://godoc.org/golang.org/x/tools/go/gcexportdata


A comparison of two interface values with identical dynamic types causes a run-time panic if values of that type are not comparable.
This behavior applies not only to direct interface value comparisons but also when comparing arrays of interface values or structs with interface-valued fields.

Go v1.15
Use an unexported, zero-width, non-comparable field
(Function values, Slice values and Map values are not comparable
https://golang.org/ref/spec#Comparison_operators ), to
prevent clients from comparing a struct and shrink binary size.
(Using 0 size of array instead of pure Function/Slice/Map which holds a size
of pointer points to memory):
type Point struct {
 _ [0] func()
 X, Y int
}

Aug 23, 2019

[Go] print out stack trace at runtime

runtime.Stack(buf, true)
Stack formats a stack trace of the calling goroutine into buf and returns the number of bytes written to buf.
If all is true, Stack formats stack traces of all other goroutines into buf after the trace for the current goroutine.


$ go doc -src runtime.Stack
$ go doc runtime.Stack

Apr 19, 2017

[Go] code snippet

http://www.tapirgames.com/blog/golang-tricks
Get the range index.
package main

import "fmt"

func main() {
 for i := range (*[10]int)(nil) { // int can be replaced with any type
  fmt.Println(i)
 }
 for i := range [10][0]int{} { // int can be replaced with any type
  fmt.Println(i)
 }
 for i := range [10]struct{}{} {
  fmt.Println(i)
 }
}


Block main goroutin forever(using select).
package main

import "time"

func main() {
 go func() {
  for {
   time.Sleep(time.Second)
  }
 }()
 
 select{} // block here for ever
}


Bits manipulte.
const MaxUint = ^uint(0)
const MaxInt  = int(^uint(0) >> 1)

const Is64bitOS = ^uint(0) >> 63 // 1 or 0
const WordBits = 32 << (^uint(0) >> 63) // 64 or 32

import "unsafe"

const Is64bitOS = unsafe.Sizeof(1) / 8
const WordBits = unsafe.Sizeof(1) * 8


compile-time assertion code in functions identified with the blank identifier
type I interface {
 f()
}

func _() {
 var _ I = T{}       // assert T implements I
 var _ I = (*T)(nil) // assert *T implements I
}

type T struct{}
func (t T) f() {}

const M = 8
const N = 8

func _() {
 // methods to assert N >= M
 var _ [N-M]int
 type _ [N-M]int
 const _ uint = N-M
 
 // methods to assert M == N
 var _ [M-N]int; var _ [N-M]int
 type _ [M-N]int; type _ [N-M]int
 const _, _ uint = M-N, N-M
}


Use recover to restart goroutine automatically
package main

import (
 "time"
 "fmt"
)

func neverExist() {
 time.Sleep(time.Second)
 panic("crashed.")
}

func autoRestart(f func()) {
 defer func() {
  recover()
  fmt.Println("restart")
  go autoRestart(f)
 }()
 
 f()
}

func main() {
 go autoRestart(neverExist)
 select{}
}


Design:
Shadow unwanted variables and types to avoid misusing them carelessly.
i.e The POWER of blocks (c++ alike)
import "database/sql"

func Exec(db *sql.DB, sqlstr string) error {
 // using db ...
 // ...

 // do transaction
 tx, err := db.Begin()
 if err != nil {
  return err
 }
 
 // sql.DB and sql.Tx have many same methods,
 // to avoid misusing the db variable below,
 // we can shaddow it.
 {
  type db complex64 // shaddow db
  
  // _, err := db.Exec(sqlstr) 
  // if we call the above line, compiler will report error.
  _, err := tx.Exec(sqlstr)
  if err != nil {
   tx.Rollback()
   return err
  }

  return tx.Commit()
 }
}