Golang中启动http.ListenAndServe后还能向通道写入数据吗

Golang中启动http.ListenAndServe后还能向通道写入数据吗

package main

import (
	"fmt"
	"net/http"
	"sync"
)

func server(done chan bool, wg *sync.WaitGroup) {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("OK"))
	})

	fmt.Println("SERVER...")
	http.ListenAndServe("localhost:8080", nil)
	done <- true
	wg.Done()
}

func main() {
	done := make(chan bool)
	wg := &sync.WaitGroup{}
	wg.Add(2)
	go server(done, wg)
	go func() {
		for d := range done {
			fmt.Println(d)
		}

	}()

	wg.Wait()
}

更多关于Golang中启动http.ListenAndServe后还能向通道写入数据吗的实战教程也可以访问 https://www.itying.com/category-94-b0.html

4 回复

能否请您更具体地说明您在这里想要实现什么?ListenAndServe 是一个阻塞调用,在关闭之前会一直运行。如果您想在启动它之后向通道传递某些内容,您需要将其放在一个 goroutine 中。

更多关于Golang中启动http.ListenAndServe后还能向通道写入数据吗的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


你好 Alexcray。 谢谢! 在这个例子中,errChan 只有在 http.ListenAndServe 返回错误时才会工作。我需要通道总是被记录。

done := make(chan bool)

该方法使用一个 WaitGroup 来追踪服务器协程,并使用一个通道来传递错误信号。其工作原理如下:

var wg sync.WaitGroup
errChan := make(chan error)

func serveHTTP() {
    err := http.ListenAndServe(":8080", nil)
    errChan <- err // 发送服务器遇到的任何错误
    wg.Done()      // 发出服务器协程完成的信号
}

func main() {
    wg.Add(1)
    go serveHTTP()

    // 你的主程序逻辑写在这里

    // 等待服务器完成(出错或停止)
    err := <-errChan
    wg.Wait()      // 确保服务器协程完全结束

    if err != nil {
        fmt.Println("Error:", err)
    } else {
        fmt.Println("Server stopped successfully")
    }
}

在此示例中,serveHTTP 函数作为一个 goroutine(异步函数)运行。errChan 通道用于发送服务器遇到的任何错误。主程序等待服务器协程完成(使用 wg.Wait()),然后检查从 errChan 接收到的错误。

是的,http.ListenAndServe 启动后仍然可以向通道写入数据。但在你的代码中存在一个关键问题:http.ListenAndServe 是阻塞调用,它后面的代码 done <- truewg.Done() 永远不会被执行。

以下是修复后的示例:

package main

import (
	"fmt"
	"net/http"
	"sync"
)

func server(done chan bool, wg *sync.WaitGroup) {
	defer wg.Done()
	
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("OK"))
	})

	fmt.Println("SERVER...")
	
	// 在一个单独的goroutine中启动服务器
	go func() {
		http.ListenAndServe("localhost:8080", nil)
	}()
	
	// 这里可以继续执行其他逻辑
	done <- true
}

func main() {
	done := make(chan bool)
	wg := &sync.WaitGroup{}
	wg.Add(2)
	
	go server(done, wg)
	
	go func() {
		defer wg.Done()
		for d := range done {
			fmt.Println("Received from done channel:", d)
		}
	}()

	wg.Wait()
	fmt.Println("All goroutines completed")
}

或者使用更简洁的方式,将服务器启动放在单独的goroutine中:

package main

import (
	"fmt"
	"net/http"
	"sync"
)

func main() {
	done := make(chan bool)
	wg := &sync.WaitGroup{}
	wg.Add(1)
	
	// 启动HTTP服务器
	go func() {
		defer wg.Done()
		
		http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
			w.Write([]byte("OK"))
		})
		
		fmt.Println("Starting server on localhost:8080")
		http.ListenAndServe("localhost:8080", nil)
	}()
	
	// 主goroutine可以继续向通道写入数据
	go func() {
		done <- true
		done <- false
		close(done)
	}()
	
	// 从通道读取数据
	for d := range done {
		fmt.Println("Channel data:", d)
	}
	
	wg.Wait()
}

关键点:

  1. http.ListenAndServe 是阻塞调用,会一直运行直到服务器关闭
  2. 需要将其放在单独的goroutine中,才能继续执行后续代码
  3. 通道操作和HTTP服务器可以在不同的goroutine中并发执行
回到顶部