Last active
June 20, 2019 08:30
-
-
Save hongkheng/abe25b1447e063632275f012f7bbca9b to your computer and use it in GitHub Desktop.
Ultimate Go notes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Variables consistency | |
var defaultZero int // always contain 0 | |
var defaultEmpty string // always be "" | |
// https://play.golang.org/p/xD_6ghgB7wm | |
// struct types | |
/** | |
Compiler does not do implicit type conversion for named type. | |
For literal type, compiler does implicit type conversion, for type = literal type | |
It is ok to have some padding happening in the struct memory unless memory efficiency is absolutely neccessary | |
**/ | |
// Pointers | |
// *int means to store the address only, is a literal type. Share a value. For efficiency. | |
// Allocation happens when the pointers are not on the stack. It will be on the heap. GC will happen. | |
// Arrays | |
// Arrays has a predictable memory access pattern | |
// https://en.wikipedia.org/wiki/Translation_lookaside_buffer | |
// https://en.wikipedia.org/wiki/Page_(computer_memory) | |
// http://frankdenneman.nl/2016/07/06/introduction-2016-numa-deep-dive-series/ | |
// Value semantics | |
// primitive types do not need to have pointers, already reduced allocations to the heap | |
// for :range | |
// Copy of original five, v is copy of the copied five | |
for i, v := range five { | |
} | |
// pointer semantics | |
for i := range five {} | |
// Array | |
// length with 2 word | |
// Slices | |
// length with 3 word | |
var data []string // nil | |
data := []string{} // empty, is a pointer that points to a empty struct value | |
var es struct{} // empty struct | |
// Reference Type | |
// Slices, value semantics | |
// Methods | |
// Factory methods will show the semantics of the Named Type | |
// no setter and getter | |
// precise APIs | |
// polymorphism | |
// behaviour of a piece of code changes based on the data being passed in | |
// Interfaces | |
// Interfaces are valueless. It does not define the semantics. | |
// reader is an interface that defines the act of reading data. | |
type reader interface { | |
read(b []byte) (int, error) // Good | |
read(n int) ([]byte, error) { // Bad | |
s := make([]byte, 1024) | |
return s | |
} | |
} | |
// retrieve can read any device and process the data. | |
// reader is an interface that defines the act of reading data. | |
// argument is the data of reader | |
func retrieve(r reader) error { | |
data := make([]byte, 100) | |
len, err := r.read(data) | |
if err != nil { | |
return err | |
} | |
fmt.Println(string(data[:len])) | |
return nil | |
} | |
// Go's iTable is similar to other languages' vTable | |
// Interface has pointers that do indirection -> allocation to the heap. | |
// Methods | |
// Some values of only exist in compile time, might not have an address | |
// Pointer semantics only allow you to share, and not make a copy | |
// Embeded Types | |
// Common to export named type and unexport name struct/interface | |
// export | |
// Software design | |
// Interfaces are for behaviour | |
// DRY is evil. Okay to copy code to mvoe things faster. | |
// Package-oriented design. Group the code by packages like microservices. | |
// Design start by the data and what data is being passed. | |
// Layering the API | |
/** | |
Export : High level API | |
--------------- | |
Un / Export: Low level API | |
------------------ | |
Primitives API | |
----------------- | |
*/ | |
// Debugger is evil | |
// No exception in Go | |
// Naked switch, single ifs with no else clauses | |
// Type as contexts. NO. | |
// Error Types: Temporary, Timeout, Not found, Not authorized | |
// Use pointer semantics for Error handling | |
// Stack trace error, call panic | |
// other just use OS Exit to shut down | |
// Packaging | |
// Do not share the same Type system. | |
// go dep | |
// https://github.com/ardanlabs/service/tree/master/internal | |
// Concurrency | |
// Multi-threaded | |
// Context switching between threads is expensive | |
// IOCP for windows for threading | |
// Scheduler in Go is co-operative. | |
// Go scheduler is part of the runtime and is at user mode, processor has 2 modes. User mode or Kernel mode. | |
// Go scheduler can switch to a kernel mode. | |
// Network poller - thread pool handles asynchronous network/system calls | |
// Move to the L. Runtime Queue | |
// Go can go up to 10000 threads before it goes into a panic mode | |
// Go routines | |
// Go code in general are not atomic. have to make atomic to inside goroutines | |
// Dun always use channels. Channel and performance do not go together. | |
// Channels | |
// Dun think channels as queues. | |
// Use for signaling | |
// Use Mutex, atomic to protect your instructions to be in sync. Without atomic, each individual instruction is on its own. | |
// Cannot simply use print statements to log order of the channels and goroutines. | |
// Buffer reduce latency, no performance gain | |
// Start cleanly. Quit cleanly with all processes/goroutines all exit on shut down. | |
// Back pressure, having time outs | |
// No increasing of buffer size. Use the data as soon as it comes, no storing of buffer. It could blow up your server. | |
// Factory functions returning an inline function. compiler does optimization and do not allocate it to the heap. | |
// Profiling | |
// GODEBUG=gctrace=1 ./project > /dev/null | |
/* | |
goroutine 1 [running]: | |
main.example(0xc000042748, 0x2, 0x4, 0x106abae, 0x5, 0xa) | |
stack_trace/example1/example1.go:13 +0x39 | |
main.main() | |
stack_trace/example1/example1.go:8 +0x72 | |
// last resort | |
+0x39 the address pointer of the next instruction if the program does not panic | |
*/ | |
// Type system is there to accept and return the data | |
// Each package should have their own type system, duplication is ok | |
// internal packages should not import each other, it can only be imported at the higher level | |
// Know the purpose of the log at the start of the program | |
// os.Stdout only for normal app, os.Stderr -> tracing, or CLI tools | |
// Configuration/env var in the main package only | |
// Flags to override the default configuration | |
// determine packages to contain or provide | |
// Context should be able to work when empty. Should only use for tracing | |
// Do not use context to pass biz logic data, database conn | |
// Only the code that own the go routine can panic |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment