如果没有goto语句,我怎样才能改进我的代码?
我的功能是从服务器读取并发送数据 到另一个处理数据的函数,我不得不添加一个 goto声明为了处理断开的连接情况, 我没有找到更好的方法来做到这一点。
你能帮我提一些建议吗?
func Reader(source string, proto string, chOutput chan string) {
init:
fmt.Println("Conectando con Source:", source)
conn, err := net.Dial(proto, source)
if err != nil {
fmt.Println("Error:", err.Error())
}
defer conn.Close()
reader := bufio.NewReader(conn)
for {
line, err := reader.ReadString('\n')
if err != nil {
fmt.Println("Error:", err.Error())
time.Sleep(1 * time.Second)
goto init
}
fmt.Println("Enviando dato a Buffer:", line)
chOutput <- line
}
}
我的功能是goroutine:
func main(){
mychan:= make(chan string)
go Reader(source, proto, mychan)
go Process(mychan)
...
}
goto或标签是解决重试连接的最佳方法吗? 还有另一种标准方法吗?
答案 0 :(得分:3)
您可以对错误处理来电者的问题并返回特殊错误:
var errRetry = errors.New("retry")
func Reader(source string, proto string, chOutput chan<- string) error {
fmt.Println("Conectando con Source:", source)
conn, err := net.Dial(proto, source)
if err != nil {
return err
}
defer conn.Close()
scanner := bufio.NewScanner(conn)
for scanner.Scan() {
line := scanner.Text()
fmt.Println("Enviando dato a Buffer:", line)
chOutput <- line
}
if err := scanner.Err(); err != nil {
return errRetry
}
return nil
}
func main() {
ch := make(chan string)
go func() {
for s := range ch {
// stuff with s
_ = s
}
}()
L:
for {
switch err := Reader("localhost:9020", "tcp4", ch); err {
case errRetry:
// do nothing to retry
case nil:
// do you want to break if the connection got closed gracefully?
break L
default:
//handle err
break L
}
}
close(ch)
}
答案 1 :(得分:0)
您可以通过引入外部循环来消除goto。如果打开连接时出现错误,请继续外循环。如果读取行有误,则跳出内循环。
完成后关闭连接。在函数返回之前,延迟不会执行。
func Reader(source string, proto string, chOutput chan string) {
for {
fmt.Println("Conectando con Source:", source)
conn, err := net.Dial(proto, source)
if err != nil {
fmt.Println("Error:", err.Error())
time.Sleep(1 * time.Second)
continue
}
reader := bufio.NewReader(conn)
for {
line, err := reader.ReadString('\n')
if err != nil {
fmt.Println("Error:", err.Error())
conn.Close()
time.Sleep(1 * time.Second)
break
}
fmt.Println("Enviando dato a Buffer:", line)
chOutput <- line
}
}
}
考虑在连接失败时使用指数退避:
func Reader(source string, proto string, chOutput chan string) {
sleep := time.Second
for {
fmt.Println("Conectando con Source:", source)
conn, err := net.Dial(proto, source)
if err != nil {
fmt.Println("Error:", err.Error())
sleep *= 2 // exponential backoff
if sleep > time.Minute {
sleep = time.Minute
}
time.Sleep(sleep)
continue
}
sleep = time.Second // Reset on success.
reader := bufio.NewReader(conn)
for {
line, err := reader.ReadString('\n')
if err != nil {
fmt.Println("Error:", err.Error())
conn.Close()
time.Sleep(sleep)
break
}
fmt.Println("Enviando dato a Buffer:", line)
chOutput <- line
}
}
}