Golang short tips & tricks
This list of short golang code tips & tricks will help keep collected knowledge in one place.
Support the project
Send some ether 0x30FD8822D15081F3c98e6A37264F8dF37a2EB416
- 70 - distributed protocols
- 69 - sql more productive
- 68 - go1.8 features
- 67 - microservices
- 66 - json rpc over any transport
- 65 - grpc
- 64 - go vs rust
- 63 - chan with timeout
- 62 - contex vs chan
- 61 - log with line number and func name
- 60 - custom queue
- 59 - go tools usage
- 58 - set go env
- 57 - Multiple concurrent http requests with timeout
- 56 - Inplace struct
- 55 - Dynamic time intervals
- 54 - NoDB
- 53 - EC operations from bitcoin core
- 52 - nil
- 51 - BBQ
- 50 - cool go links
- 49 - custom wait group
- 48 - ev_loop vs co_routine
- 47 - Use C for computation intensive operations
- 46 - Unique key doc manipulation in MonGo
- 45 - Go is more a framework than a language
- 44 - Facebook messenger chatbot
- 43 - Passing args as a map
- 42 - Optimize Go
- 41 - Telegram bot
- 40 - Distributed consensus
- 39 - Public private struct fields and funcs
- 38 - Marshal Unmarshal to byte slice using gob
- 37 - Time series on leveldb
- 36 - Custom type marshal unmarshal json
- 35 - Test specific functions
- 34 - File path exists
- 33 - Table driven tests
- 32 - Work with consul
- 31 - Do not need any web framework
- 30 - Heart beat and lead election with etcd
- 29 - Partial json read
- 28 - Interact with etcd with http.Request
- 27 - Go-style concurrency in C
- 26 - Go channels are slow
- 25 - Avoid conversions with hidden alloc copy
- 24 - Slice shuffle
- 23 - Defer is slow
- 22 - Any number of args
- 21 - Test bench http request handler
- 20 - Use Atomics or GOMAXPROCS=1
- 19 - Chunked HTTP response with flusher
- 18 - Use for range for channels
- 17 - Use context API
- 16 - Go routines syncronization
- 15 - Time interval measurement
- 14 - Benchmark switch vs else if
- 13 - Use ASM in Go Code
- 12 - JSON with unknown structure
- 11 - Websocket over HTTP2
- 10 - HTTP2
- 9 - Error handling
- 8 - Memory management with pools of objects
- 7 - Sort slice of time periods
- 6 - Fast http server
- 5 - Close channel to notify many
- 4 - Is channel closed?
- 3 - Http request/response with close notify and timeout
- 2 - Import packages
- 1 - Map
- 0 - Slices
2017-03-15 by @beyondns
Distributed protocol can be divided into two parts: serve incommin' requests (passive), make outgoin' requests (active)
- An open protocol for decentralized exchange on the Ethereum blockchain
- bitcoin
- ethereum
- graphene
- chain
- raft
- zcash
2017-03-06 by @beyondns
- How Modern SQL Databases Come up with Algorithms that You Would Have Never Dreamed Of by Lukas Eder
- Using PostgreSQL with Golang
2017-02-17 by @beyondns
package main
import (
"log"
"io"
"os"
"os/signal"
"net/http"
"context"
"golang.org/x/net/http2"
)
type handl struct{}
func (*handl) ServeHTTP(w http.ResponseWriter, r *http.Request) {
log.Printf("%v",r.URL)
io.WriteString(w, "Hello")
if p, ok := w.(http.Pusher); ok {
p.Push("/static/1.jpg", nil)
}
}
func main() {
quit := make(chan os.Signal)
signal.Notify(quit, os.Interrupt)
srv := &http.Server{Addr: ":8080", Handler: &handl{}}
go func() {
<-quit
err := srv.Shutdown(context.Background())
if err != nil {
log.Fatal(err)
}
}()
http2.ConfigureServer(srv, nil)
// openssl req -x509 -newkey rsa:2048 -nodes -keyout srv.key -out srv.cert -days 365
err := srv.ListenAndServeTLS("srv.cert", "srv.key")
if err != nil {
log.Fatal(err)
}
}
// js client
var http2 = require('http2');
http2.globalAgent = new http2.Agent({
rejectUnauthorized: false
});
var request = http2.get('https://localhost:8080/');
request.on('response', function(response) {
response.pipe(process.stdout);
});
request.on('push', function(pushRequest) {
console.log('Receiving pushed resource: ' + pushRequest.url);
pushRequest.on('response', function(pushResponse) {
console.dir('Receiving pushed response: ' + pushResponse);
});
});
2017-01-31 by @beyondns
It's an approach to handle complexity
2017-01-31 by @beyondns
package main
import (
"encoding/json"
"errors"
"fmt"
"log"
)
const transpostJSON = `
{
"version": "0.1",
"id": "1234567",
"method": "transpost",
"params": {
"data":{
"timestamp":"2017-01-20T15:50:41.163Z"
},
"hash":"acfd55c995be410bbda4ee78f921608db42b3c10a5f44a1a5d15b1c0a7138e0e",
"signs": [
{
"pub": "03ab4b14fe08f81e56af1d731f6c22c0a860c2c3c9c7b91d9c190aa602cf97f668",
"sign": "bfb7fc15f336b802310d9c38288ecacc0c5fadda31a564c120e63e6ee5a4d8ae5beaaeae75007d1fac97e77520087f86823f98a25b2f3be51eac47fec862c2ee",
"date": "2017-01-31T18:38:24.057Z"
}
]
}
}
`
type (
RemoteRequest struct {
Version string `json:"version"`
Id string `json:"id,omitempty"`
Method string `json:"method"`
Params json.RawMessage `json:"params,omitempty"`
}
Transaction struct {
Data TransData `json:"data"`
Hash string `json:"hash"`
Signs []TransSign `json:"signs"`
}
TransData struct {
Timestamp string `json:"timestamp"`
}
TransSign struct {
Pub string `json:"pub"`
Sign string `json:"sign"`
Date string `json:"date"`
}
RemoteResponse struct {
Version string `json:"version"`
Id string `json:"id,omitempty"`
Status string `json:"status"`
}
)
func processTransPost(data []byte) ([]byte, error) {
tx:=&Transaction{}
err := json.Unmarshal(data, tx)
if err != nil {
log.Printf("json.Unmarshal %v", err)
return nil, err
}
log.Printf("tx:%v",tx)
return []byte(`{"status":"ok"}`), nil
}
func processTransVerify(data []byte) ([]byte, error) {
return nil, errors.New("processTransVerify not implemented")
}
func processHeartBeat(data []byte) ([]byte, error) {
return nil, errors.New("processHeartBeat not implemented")
}
func processRemote(data []byte) ([]byte, error) {
req := &RemoteRequest{}
err := json.Unmarshal(data, req)
if err != nil {
log.Printf("json.Unmarshal %v", err)
return nil, err
}
switch req.Method {
case "transpost":
return processTransPost(req.Params)
case "transverify":
return processTransVerify(req.Params)
case "heartbeat":
return processHeartBeat(req.Params)
}
return nil, errors.New(fmt.Sprintf("unknown method %s", req.Method))
}
func main() {
bin, err := processRemote([]byte(transpostJSON))
if err != nil {
log.Fatal(err)
}
log.Printf(string(bin))
}
2017-01-26 by @beyondns
syntax = "proto3";
package remote;
service Inter {
rpc HandShake (HandShakeData) returns (HandShakeResult) {}
}
message HandShakeData {
int32 no = 1;
string query = 2;
}
message HandShakeResult {
int32 no = 1;
string res = 2;
}
package main
import (
"flag"
"log"
"net"
"strings"
"golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
pb "./remote"
)
// go get google.golang.org/grpc
// go get -u github.com/golang/protobuf/{proto,protoc-gen-go}
// protoc -I ./remote/ ./remote/rem.proto --go_out=plugins=grpc:remote
type server struct{
host *string
}
func (s *server) HandShake(ctx context.Context, in *pb.HandShakeData) (*pb.HandShakeResult, error) {
log.Printf("HandShake %v", in)
res := &pb.HandShakeResult{
Res: fmt.Sprintf("Response from %s to query %s" + s.host,in.Query),
}
return res, nil
}
// ./node -host 127.0.0.1:50051
// ./node -host 127.0.0.1:50052
func main() {
host := flag.String("host", "127.0.0.1:50051", "host host:port")
nodes := flag.String("nodes", "127.0.0.1:50051,127.0.0.1:50052,127.0.0.1:50053",
"[host:port,host:port,...]")
flag.Parse()
go func() {
lis, err := net.Listen("tcp", *host)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterInterServer(s, &server{host:host})
reflection.Register(s)
log.Printf("Serve...")
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}()
for _, n := range strings.Split(*nodes, ",") {
if n != *host {
go func(n string) {
conn, err := grpc.Dial(n, grpc.WithInsecure())
if err != nil {
log.Printf("did not connect:%s %v", n, err)
return
}
defer conn.Close()
c := pb.NewInterClient(conn)
r, err := c.HandShake(context.Background(),
&pb.HandShakeData{No: 1, Query: "hello"})
if err != nil {
log.Printf("could not HandShake: %v", err)
return
}
log.Printf("HandShake:%s %s", n, r.Res)
}(n)
}
}
select {}
}
2017-01-20 by @beyondns