This is a creation in Article, where the information may have evolved or changed.
1. A channel that has been closed will never block. Once a channel is closed, it is no longer possible to send data to the channel, but it can still try to get the value from the channel.
2. The channel that has been closed is returned in real time.
Package Mainimport ("FMT" "Sync" "Time") Func main () {const-n = 100000finish: = Make (chan bool) var-Done sync. Waitgroupfor I: = 0; I < n; i++ {done. ADD (1) go func () {select {case <-time. After (1 * time. Hour): Case <-finish:}done. Done ()} ()}t0: = time. Now () Close (finish) is done. Wait () fmt. Printf ("Waited%v for%d goroutines to Stop\n", time. Since (t0), N)}
When the finish channel is closed, it returns immediately. Then all waits to receive time. The SELECT statement for the after channel or finish Goroutine is completed immediately, and Goroutine is called done. Done () to reduce the Waitgroup counter after exiting. This powerful mechanism makes it possible to send signals to them without having to know any details of the unknown number of goroutine, without worrying about deadlocks.
When close relies on the message mechanism to close the channel, and no data is sent and received, the definition of finish as type Chan struct{} means that the channel has no data and is only interested in its closed properties. i.e.: Finish: = Make (chan struct{})
3. When the value of the channel has not been initialized or is assigned nil, it is always blocked.
Waitmany (), once a value is received, the reference to a or B is set to nil. When the nil channel is part of a SELECT statement, it is actually ignored, so setting a to nil removes it from select, leaving only b waiting for it to be closed, and then exiting the loop.
4. Various techniques of slice append function
Add Slice a = append (A, B, C, D)//Add slice B to slice aa=append (A, b ...) Copy Slice B: = make ([]int, Len (a)) copy (b, a)//delete the specified position element [i:j]a = append (A[:i], a[j:] ...) Delete Nth Element a = append (A[:n], a[n+1:] ...) Expand n Empty Elements a = append (A, make ([]int, N) ...) Insert J empty Element a = append (A[:i], append (Make ([]int, J), A[i:] In the first place ...) ...) Insert element in the i position xa = append (A[:i], append ([]int{x}, A[i:] ...) ...) Insert a slice in i position a = append (A[:i], append ([]int{x, y}, A[i:] ...) ...)
Where the delete operation is overwrite, and the insert operation needs to be careful not to overwrite the insertion position and subsequent elements.
5. Questions about string and []byte, []rune-to-cross conversion:
str: = "Hello World" SLI: = []rune (str) []rune is the go built-in function that converts the string into UTF8 encoding to {h,e,l,l,o, world, bounds} corresponding number { 104,101,108,108,111,19990,30028} byt: = []byte (str) []byte is a go built-in function that converts str to a byte slice { 104,101,108,108,111,228,184,150,231,149,140} for _,c: = Range str{ println (c) } len (str) return One Len returns a string of byte-length characters in the go, which can be ascii/Chinese . S: = ' You ' string (SLI)/string (byt) all return "Hello World" string () is a go built-in function either []rune or []byte] can return the corresponding string through the string () function
6. in the use of multiple goroutine printing content, often because the use of Chan inappropriate to
cause the main thread did not wait for the completion of all other goroutine complete and hurried to the issue, resulting in the printing content is not complete, here is a situation to explain.
The package main import ( "FMT" "runtime")//is superimposed from 1 to 100 million cycles and prints the results. Func print (c chan bool, n int) { x: = 0 for i: = 1; I <= 100000000; i++ { x + = i } fmt. PRINTLN (n, x) if n = = 9 { c <-true }} func main () { //Use multicore Run program runtime. Gomaxprocs (runtime. NUMCPU ()) c: = Make (chan bool) for I: = 0; i <; i++ { go print (c, i) } <-c fmt. Println ("Done.")}
This code is logically plausible, but it is a very
OpportunisticThe implementation of the 10th goroutine, according to the
in hasteIt is considered that the previous 9 goroutine have been executed. If you will ' Runtime. Gomaxprocs (runtime. NUMCPU ()) 'If you use a single core to run the program, you will get the results you expect, but if you are using multicore, this is
of the wrong。
Goroutine are independent of each other and may cause several of these goroutine to yield time slices to the CPU to perform other goroutine during execution. So, we
can not rely onThe execution result of the 10th goroutine to determine the operation of the program.
Solution one: Take advantage of Chan's caching mechanism
The package main import ( "FMT" "runtime")//is superimposed from 1 to 100 million cycles and prints the results. Func print (c chan bool, n int) { x: = 0 for i: = 1; I <= 100000000; i++ { x + = i } fmt. PRINTLN (n, x) C <-true} func main () { //using multi-core run program runtime. Gomaxprocs (runtime. NUMCPU ()) c: = Make (chan bool, ten) for I: = 0; i <; i++ { go print (c, i) } for I: = 0; I &l T 10; i++ { <-c } fmt. Println ("Done.")}
Solution Two:
Waitgroup using the Sync pack
The package main import ( "FMT" " runtime" " Sync")//is superimposed from 1 to 100 million cycles and prints the results. Func Print (WG *sync. Waitgroup, n int) { x: = 0 for i: = 1; I <= 100000000; i++ { x + = i } fmt. PRINTLN (n, x) //identifies a task completion WG. Done ()} func main () { //using multi-core run program runtime. Gomaxprocs (runtime. NUMCPU ()) //Create wait Group WG: = Sync. waitgroup{} //Set the number of objects to wait for WG. ADD () for I: = 0; i <; i++ { go print (&WG, i) } //wait for all tasks to complete the WG. Wait () FMT. Println ("Done.")}
7. Golang HTTP request Optimization
To determine whether the URL is valid//does not start with/HTTP, add http://if!strings. Hasprefix (Feed, "http") {feed = "//" + feed}//determine if the URL is reasonable host, err: = URL. Parserequesturi (FEED) if err! = Nil {}//Determines whether it can resolve to the corresponding host record _, err = net. Lookupip (host. Host) If Err! = Nil {}//Requests data client to host: = &http. client{Transport: &http. transport{Dial:func (netw, addr string) (net. Conn, error) {deadline: = time. Now (). ADD (Ten * time. Second) C, err: = Net. Dialtimeout (NETW, addr, 5*time. Second)//Connection time-out if err! = Nil {return nil, err} c.setdeadline (Deadline) Return c, nil},},}req, err: = http. Newrequest ("GET", feed, nil) if err! = Nil {}//data transfer compression//tells the host to support Gzip data request back after Ungzipreq. Header.set ("User-agent", "mozilla/5.0" (compatible; ujcspider/0.1; +HTTP://UJIECAO.COM/HELP) ") req. Header.set ("accept-encoding", "gzip") resp, err: = client. Do (req) if err! = nil {}defer resp. Body.close () var reader io. Readcloserswitch resp. Header.get ("Content-encodiNg ") {case" gzip ": reader, _ = gzip. Newreader (resp. Body) Defer reader. Close () Default:reader = resp. Body}