2014-10-13 4 views
0

goto 문없이 코드를 개선하려면 어떻게해야합니까?끊어진 연결의 경우 goto 문을 사용하지 않고 네트워크 코드를 개선하십시오.

내 함수는 서버에서 읽고 데이터를 처리하는 다른 함수에 데이터를 를 보내고, 내가 연결이 끊어진 경우를 처리하기 위해 고토 문을 추가했다, 내가 할 수있는 더 좋은 방법을 찾을 수 없습니다 그.

몇 가지 조언을 제공해 주시겠습니까? 고토 또는 라벨이 재시도 연결을 해결하는 가장 좋은 방법은

func main(){ 
    mychan:= make(chan string) 
    go Reader(source, proto, mychan) 
    go Process(mychan) 
    ... 

} 

인가 :

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입니까? 다른 표준 방법이 있습니까?

답변

0

당신은 외부 루프를 도입하여 고토를 제거 할 수 있습니다. 연결을 여는 동안 오류가 발생하면 외부 루프를 계속하십시오. 라인을 읽는 데 오류가있는 경우 내부 루프를 벗어나십시오.

작업이 끝나면 연결을 닫습니다. 지연은 함수가 리턴 할 때까지 실행되지 않습니다.

이 마이크로 소프트의
+0

그게 내가 찾고 있었어, 고마워. – Jzala

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

레이몬드 첸 흥미로운 게시물을 작성한 사람

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 } } } 
, http://blogs.msdn.com/ ([자동 재 시도에 진정해] :
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 } } } 

는 연결 실패에 지수 백 오프를 사용하는 것을 고려 b/oldnewthing/archive/2005/11/07/489807.aspx), 1) 낮은 수준의 재시도가 높은 수준의 재시도와 결합되면 재시도 횟수가 늘어날 수 있고 2) 재 시도가 너무 많으면 빨리 실패 할 무언가가 천천히 실패합니다. 나에게 이것은 일반적으로 스택의 맨 위에서이 대답이 제안하는대로 다시 시도하는 것을 선호해야한다고 제안한다. – twotwotwo

관련 문제