package main; import ( "sync" "fmt" "net" "runtime" ) //sync.Pool是一個能夠存或取的臨時對象集合 //sync.Pool能夠安全被多個線程同時使用,保證線程安全 //注意、注意、注意,sync.Pool中保存的任何項均可能隨時不作通知的釋放掉,因此不適合用於像socket長鏈接或數據庫鏈接池。 //sync.Pool主要用途是增長臨時對象的重用率,減小GC負擔。 func testTcpConnPool() { sp2 := sync.Pool{ New: func() interface{} { conn, err := net.Dial("tcp", ":80"); if err != nil { return nil; } return conn; }, }; buf := make([]byte, 1024); //獲取對象 conn := sp2.Get().(net.Conn); //使用對象 conn.Write([]byte("GET / HTTP/1.1 \r\n\r\n")); n, _ := conn.Read(buf); fmt.Println("conn read : ", string(buf[:n])); //打印conn的地址 fmt.Println(conn); //把對象放回池中 sp2.Put(conn); //咱們人爲的進行一次垃圾回收 runtime.GC(); //再次獲取池中的對象 conn2 := sp2.Get().(net.Conn); //這時發現conn2的地址與上面的conn的地址不同了 //說明池中咱們以前放回的對象被所有清除了,顯然這並非咱們想看到的 //因此sync.Pool不適合用於scoket長鏈接或數據庫鏈接池 fmt.Println(conn2); } func main() { //咱們建立一個Pool,並實現New()函數 sp := sync.Pool{ //New()函數的做用是當咱們從Pool中Get()對象時,若是Pool爲空,則先經過New建立一個對象,插入Pool中,而後返回對象。 New: func() interface{} { return make([]int, 16); }, }; item := sp.Get(); //打印能夠看到,咱們經過New返回的大小爲16的[]int fmt.Println("item : ", item); //而後咱們對item進行操做 //New()返回的是interface{},咱們須要經過類型斷言來轉換 for i := 0; i < len(item.([]int)); i++ { item.([]int)[i] = i; } fmt.Println("item : ", item); //使用完後,咱們把item放回池中,讓對象能夠重用 sp.Put(item); //再次從池中獲取對象 item2 := sp.Get(); //注意這裏獲取的對象就是上面咱們放回池中的對象 fmt.Println("item2 : ", item2); //咱們再次獲取對象 item3 := sp.Get(); //由於池中的對象已經沒有了,因此又從新經過New()建立一個新對象,放入池中,而後返回 //因此item3是大小爲16的空[]int fmt.Println("item3 : ", item3); //測試sync.Pool保存socket長鏈接池 testTcpConnPool(); }