2016-07-14 51 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