code: func Listen(opts Options) error {
  	mu.Lock()
  	defer mu.Unlock()
  
  	if portfile != "" {
  		return fmt.Errorf("gops: agent already listening at: %v", listener.Addr())
  	}
  
  	// new
  	gopsdir := opts.ConfigDir
  	if gopsdir == "" {
  		cfgDir, err := internal.ConfigDir()
  		if err != nil {
  			return err
  		}
  		gopsdir = cfgDir
  	}
  
  	err := os.MkdirAll(gopsdir, os.ModePerm)
  	if err != nil {
  		return err
  	}
  	if opts.ShutdownCleanup {
  		gracefulShutdown()
  	}
  
  	addr := opts.Addr
  	if addr == "" {
  		addr = defaultAddr
  	}
  	ln, err := net.Listen("tcp", addr)
  	if err != nil {
  		return err
  	}
  	listener = ln
  	port := listener.Addr().(*net.TCPAddr).Port
  	portfile = fmt.Sprintf("%s/%d", gopsdir, os.Getpid())
  	err = ioutil.WriteFile(portfile, []byte(strconv.Itoa(port)), os.ModePerm)
  	if err != nil {
  		return err
  	}
  
  	go listen()
  	return nil
  }
docs: // Listen starts the gops agent on a host process. Once agent started, users
  // can use the advanced gops features. The agent will listen to Interrupt
  // signals and exit the process, if you need to perform further work on the
  // Interrupt signal use the options parameter to configure the agent
  // accordingly.
  //
  // Note: The agent exposes an endpoint via a TCP connection that can be used by
  // any program on the system. Review your security requirements before starting
  // the agent.