This is a creation in Article, where the information may have evolved or changed.
Getting Started with Go language development
Each Go program contains a package called main and its main function, after initialization, the program executes from main, avoiding the introduction of unused packages (compilation does not pass)
Basic syntax
Basic data types
bool, byteint,int8,int16,int32,int64uint8,uint16,uint32,uint64 float32,float64(没有float类型)string
Assigning values to variables
var aa = 12a := 12a,b :=12,23
Constant Value Assignment
const( a = iota b)
Loops only for
for i:=0;i<10;i++{ do Something...}for{ //相当于while(true){}}for _,v:= range list{ //range用法返回list数组或者列表的k,v两个值(k数组索引从0开始,v值) fmt.Print("%s", v)}
Select if and switch
a := 1b := 1if a+b > 2 { // 注:if(条件不带括号,且左大括号与if保持同行)}
- Learning a language will circulate
Full demo big white equals white fat. What is the number of the large, white and fat?
package mainimport ( "fmt" "strconv")/* 大白加大白等于白胖胖.求大,白,胖各是数字多少? */func main() { for d := 1; d < 10; d++ { for b := 1; b < 10; b++ { for p := 1; p < 10; p++ { daBai, _ := strconv.Atoi(strconv.Itoa(d) + strconv.Itoa(b)) // fmt.Println("大白", daBai) baiPangPang, _ := strconv.Atoi(strconv.Itoa(b) + strconv.Itoa(p) + strconv.Itoa(p)) // fmt.Println("白胖胖", baiPangPang) if daBai+daBai == baiPangPang { fmt.Println("-------------------大 白 胖--------------------") fmt.Printf("大 = %d, 白 = %d, 胖 = %d\n", d, b, p) fmt.Println("白胖胖: ", baiPangPang) } } } }}
Data (array) and slices (slice)
Array declaration: arraytype = "[" Arraylength "]" ElementType.
var a [32] intvar b [3][5] int
(1) An array is a value type. Assigning an array to another will copy all the elements.
(2) If you pass an array to the function, it will receive a copy of the array instead of its pointer.
(3) The size of the array is part of its type, and the type [10]int and [20]int are different. After the array length is declared, it cannot be changed.
Slice declaration: Slicetype = "["] "ElementType".
var a []int
(1) The slice without initialization is nil.
(2) a slice (slice) is encapsulated in an array, in effect, a slice can be seen as a dynamically varying size.
(3) Most of the array programming in GO is done through slices, not simple arrays.
In general, there are two ways to initialize a slice:
//通过数组方式var myArray [10]int = [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}var mySlice []int = myArray[:5]//make方式make([]T, length, capacity)
Channel
Goroutine and channel are two core feature of go in "concurrency".
Channel is a way of communication between Goroutine, and go advocates the "communication as a means to share memory" the most direct embodiment.
Channel statement:
Channeltype = ("Chan" | "Chan" "<-" | "<-" "Chan") ElementType.
var ch Chan int
var ch1 chan<-int//ch1 can only be written
var ch2 <-chan int//CH2 Read Only
Make initialization
Putnamechan: = Make (chan string, 100)//with Buffering
Goroutine
Keyword go, the only way to enable Goroutine
//同时向五个人打招呼func main(){ names := []string{"Eric","Tom","Jack","Jim"} for _,name:= range names{ go func(){ fmt.Printf("Hello,%s.\n",name) }() } runtime.Gosched()}
Scheduling model
There are three important structures inside the GO scheduler: m,p,s
- M: Represents the real kernel OS thread, the real working man
- G: Represents a goroutine, it has its own stack, instruction pointer and other information (waiting for the channel, etc.) for dispatch.
P: Represents the context of a dispatch, which can be seen as a local scheduler that allows go code to run on a thread, which is the key to implementing mapping from N:1 to n:m.
In the figure, there are 2 physical threads m, each of which has a context (P), and each has a running goroutine.
The number of P can be set by Gomaxprocs (), which in fact represents the true concurrency, that is, how many goroutine can run at the same time.
The gray goroutine in the figure are not running, but are ready for readiness and are waiting to be dispatched. P maintains this queue (called Runqueue),
In the go language, it's easy to start a goroutine: Go function is OK, so every go statement is executed, and the Runqueue queue adds a
Goroutine, at the next dispatch point, remove a goroutine execution from the runqueue.
Other
- Defer statement: When calling a function that is defer, delay execution before the function is just going to return
- Panic/recover Exception Handling Statements
Defects
- Compile-generated executable file size is very large
- Poor code readability (x, y, z int, a []*struct)
- Go abuse leads to unpredictable bugs (note goroutine use should be conservative)
There are two kinds of thinking logic that will think of using goroutine
- Business logic requires concurrency
For example, a server, receiving a request, the blocking method is that a request processing is completed before the processing of a second request begins. In fact, in the design we will not do this, we will be in the beginning to think of the use of concurrency to handle this scenario, each request to start a goroutine to serve it, so that the parallel effect. This kind of goroutine directly according to the logic of thinking to use Goroutine
- Performance optimization requires concurrency
One scenario is this: a message needs to be sent to a group of users, and normal logic uses
for _, user := range users { sendMessage(user)}//但是在考虑到性能问题的时候,我们就不会这样做,如果users的个数很大,比如有1000万个用户?我们就没必要将1000万个用户放在一个routine中运行处理,考虑将1000万用户分成1000份, //每份开一个goroutine,一个goroutine分发1万个用户,这样在效率上会提升很多。这种是性能优化上对goroutine的需求
Example HTTPMQ
HTTP protocol implementation of Message Queuing, data persistence leveldb
HTTPMQ MUX: = http. Newservemux () Mux. Handlefunc ("/", Func (w http.) Responsewriter, R *http. Request) {}//net/http Packet routing for Interception Processing (Put,get,status,view)//Receive Name\data parameters//up to four channelputnamechan: = Make (chan string, 100) Queue name Pipeline Putposchan: = Make (chan string, 100)//Queue Data index pipeline Getnamechan: = Do (chan string, 100)//Outbound name pipeline Getposchan: = ma Ke (chan string, 100)//out of line Data index pipeline//two goroutine do message pipeline incoming team out operation go func (Chan string, chan string) {for {name: = <- Putnamechan//Putpos: = Httpmq_now_putpos (name) Putposchan <-Putpos}} (Putnamechan, Putposchan) go f UNC (Chan string, chan string) {for {name: = <-getnamechan GetPos: = Httpmq_now_getpos (name) g Etposchan <-GetPos}} (Getnamechan, Getposchan)//put queued operation Putnamechan <-nameputpos: = <-putposchanqueue_name: = Name + putposif Data! = "" {db. Put ([]byte (Queue_name), []byte (data), nil)} else if Len (BUF) > 0 {db. Put ([]byte (Queue_name), buf, nil)}//get out the team operation Getnamechan <- Namegetpos: = <-getposchanif GetPos = = "0" {w.write ([]byte ("Httpmq_get_end")}} else {queue_name: = name + GetPos V, err: = db. Get ([]byte (queue_name), nil) if Err = = nil {W.header (). Set ("Pos", GetPos) W.write (v)} else {w.write ([]byte ("Httpmq_get_error")}}}
Put operation
Name-to-putnamechannel-generation Putpos--putposchannel--Name+pos generate key persistence data
Get operation
Name-to-getnamechannel-build GetPos-getposchannel-name+pos generate key GetData