2016-07-14 44 views
-1

我有一個封閉,我聲明和定義局部變量:內存管理轉到

func writer_factory() func() *net.TCPConn { 

    response_port := "localhost:8000" 
    tcpAddr_res, err := net.ResolveTCPAddr("tcp4", response_port) 
    checkError(err) 
    var response_writer *net.TCPConn 
    checkError(err) 
    return func() *net.TCPConn { 
     if response_writer == nil{ 
      response_writer, err = net.DialTCP("tcp", nil, tcpAddr_res) 
      checkError(err) 
     } 
     return response_writer 
    } 
} 

現在的問題是,如果我把這個writer_factory多次將我得到一個內存泄漏?

那麼具體的,將我在這個程序中使用writer_factory內存泄漏:

package main 


import (
    "fmt" 
    "net" 
    "os" 
    "strings" 
// "io/ioutil" 


) 

//fmt.Printf("messages are (1) %q\n", messages) 

func main() { 

    end_of_message_terminator := "||" 
    beginning_of_next_message := "" 
    request := make([]byte, 512) 

    service_port := ":7777" 
    tcpAddr, err := net.ResolveTCPAddr("tcp4", service_port) 
    checkError(err) 
    listener, err := net.ListenTCP("tcp", tcpAddr) 
    checkError(err) 



    for { 
     response_writer := writer_factory() 

     conn, err := listener.Accept() 

     if err != nil { 

      continue 

     } 

     read_len, err := conn.Read(request) 

     if read_len == 0 { 
      continue 
     } 

     request_string := string(request[:read_len]) 


     messages := strings.Split(request_string, end_of_message_terminator) 


     messages[0] = beginning_of_next_message + messages[0] 

     if messages[len(messages) - 1] != "" { 
      beginning_of_next_message = messages[len(messages) - 1] 
      messages[len(messages) - 1] = "" 

     } 

     if len(messages) == 1 { 
      continue 
     } 

     rw := response_writer() 
     join_channel := make(chan struct{}) 
     for i := 0; i < len(messages); i++ { 


      go func(i int, rw *net.TCPConn){ 

       respond_to_message(messages[i], rw) 
       join_channel <- struct{}{} 

      }(i, rw) 


     } 

     go func(){ 

      for i := 0; i < len(messages); i++ { 

       <- join_channel 

      } 


      rw.Close() 

     }() 
     conn.Close() 


    } 

} 


func writer_factory() func() *net.TCPConn { 

    response_port := "localhost:8000" 
    tcpAddr_res, err := net.ResolveTCPAddr("tcp4", response_port) 
    checkError(err) 
    var response_writer *net.TCPConn 
    checkError(err) 
    return func() *net.TCPConn { 
     if response_writer == nil{ 
      response_writer, err = net.DialTCP("tcp", nil, tcpAddr_res) 
      checkError(err) 
     } 
     return response_writer 
    } 
} 


func respond_to_message(message string, response_writer *net.TCPConn){ 

    message_parameters := strings.Split(message, "|") 

    //response_writer.Write([]byte("asti de chris")) 
    for i := range message_parameters { 




     param_parts := strings.Split(message_parameters[i], "=") 

     param_name := param_parts[0] 

     //param_value := param_parts[1] 


     response_writer.Write([]byte(param_name)) 

     //fmt.Println(string(result)) 




    } 


} 


func checkError(err error) { 

    if err != nil { 

     fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error()) 
     os.Exit(1) 

    } 

} 

行使此代碼啓動該程序,然後啓動這個程序netcat -l -p 8000,然後該程序printf "asti||" | netcat localhost 7777

+6

Go中很少有東西可能導致內存泄漏('time.Tick'是目前唯一想到的)。如果你不能訪問一個值(即它的引用已經消失),它將在未來某個時候收集垃圾。 –

+0

我很確定你必須關閉一個TCPConn,否則你會得到,如果不是內存泄漏,至少有一個文件指針泄漏。 – Adrian

回答

0

你可以通過使用一個連接或者(如果一個連接不是線程保存)肯定會提高性能,請使用sync.Pool。這將節省你的內存分配(並利用它進行垃圾回收),並且浪費時間打開所有這些tcp連接。

+0

但我確實收不到?像這樣:'去func(){0} 0 {0}我

+0

對不起。不知道在將連接重新放回同步池時將連接保持打開是否明智。也許別人知道? – TehSphinX