2013-04-20 3 views
9

나는 매우 새로운 오류 처리 기능을 제공합니다. 나는 그것에 대한 추론을 읽고 거의 동의하지만 실제로 작업을 수행하는 것보다 오류를 처리 할 코드가 더 많이있는 곳이 몇 군데 있습니다. 다음은 (고안된) 예제입니다. 여기서 "Hello world!" 고양이에 넣고 출력을 읽고 출력하십시오. 기본적으로 모든 행에는 오류를 처리 할 수있는 세 가지가 더 있으며 실제로 아무 것도 처리하지 않습니다.여러 오류를 처리하는 중

package main 

import "fmt" 
import "io" 
import "io/ioutil" 
import "os/exec" 


func main() { 
    cmd := exec.Command("cat", "-") 
    stdin, err := cmd.StdinPipe() 
    if err != nil { 
     return 
    } 
    stdout, err := cmd.StdoutPipe() 
    if err != nil { 
     return 
    } 
    err = cmd.Start() 
    if err != nil { 
     return 
    } 
    _, err = io.WriteString(stdin, "Hello world!") 
    if err != nil { 
     return 
    } 
    err = stdin.Close(); 
    if err != nil { 
     return 
    } 
    output, err := ioutil.ReadAll(stdout) 
    if err != nil { 
     return 
    } 
    fmt.Println(string(output)) 
    return 
} 

이 문제를 해결하는 관용의 깨끗한 방법이 있습니까? 나는 뭔가를 놓치고있는 것 같아.

+1

http://stackoverflow.com/questions/15397419/go-handling-multiple-errors-elegantly?rq=1 –

답변

7

분명히 우리는 오류를 처리해야합니다. 우리는 단지 그들을 무시할 수 없다. 예 덜 인공 만들려고 예를 들어

,

package main 

import (
    "fmt" 
    "io" 
    "io/ioutil" 
    "os" 
    "os/exec" 
) 

func piping(input string) (string, error) { 
    cmd := exec.Command("cat", "-") 
    stdin, err := cmd.StdinPipe() 
    if err != nil { 
     return "", err 
    } 
    stdout, err := cmd.StdoutPipe() 
    if err != nil { 
     return "", err 
    } 
    err = cmd.Start() 
    if err != nil { 
     return "", err 
    } 
    _, err = io.WriteString(stdin, input) 
    if err != nil { 
     return "", err 
    } 
    err = stdin.Close() 
    if err != nil { 
     return "", err 
    } 
    all, err := ioutil.ReadAll(stdout) 
    output := string(all) 
    if err != nil { 
     return output, err 
    } 
    return output, nil 
} 

func main() { 
    in := "Hello world!" 
    fmt.Println(in) 
    out, err := piping(in) 
    if err != nil { 
     fmt.Println(err) 
     os.Exit(1) 
    } 
    fmt.Println(out) 
} 

출력 : 이동에

Hello world! 
Hello world! 

Error Handling and Go

는 오류 처리가 중요합니다. 언어 디자인과 규칙을 사용하면 예외가 발생했는지 다른 언어로 된 예외 ( 예외를 던지거나 때로는 잡기)와 다른 오류를 명시 적으로 확인하는 것이 좋습니다. 경우에 따라 Go 코드가 길어집니다. 관용적를 들어

+1

이 반복 코드의 많은 문제가 해결되지 않습니다. 더 나은 솔루션을 얻으려면 [질문 user2303335 링크] (http://stackoverflow.com/questions/15397419/go-handling-multiple-errors-elegantly)를 참조하십시오. – amon

+4

@amon : 연결된 질문에 대한 답변이 모두 만족스럽지 않습니다. 핵심 Go 라이브러리에 대한 모범 사례 [Go source code] (https://code.google.com/p/go/source/browse/)를 읽으십시오. 의도적으로 Go 코드는 오류를 검사합니다. 질문에 직접 코드를 다시 작성하고 우리가 생각해내는 것을 보여주십시오. – peterSO

0

, 오류를 반환하는 주제에 터치 시작하고,이 동안 통화의 맥락과 관련된 정보의 일부 여분의 비트와 함께 오류를 포장하여 더 취할 수 peterSO의 대답을 참조하여 신청.

이 작업을 통해 반복적 인 실행은 다음 링크에서 일부 비정상적으로 창조적 예제와 함께 더 일반화 된 것을 보증 할 수의 경우 수,하지만 난 그 질문에 댓글을 달았습니다, 검사 나쁜 코드 예제였다 수 Go — handling multiple errors elegantly?

당신이 가지고있는 예제만을 보더라도, 이것은 메인에서 일회용으로 쓰일뿐입니다. 그래서 대화 형 파이썬 콘솔에서 할 수있는 것처럼 혼란스러워하는 것처럼 취급하십시오.

package main 

import (
    "fmt" 
    "io" 
    "io/ioutil" 
    "os/exec" 
) 

func main() { 
    cmd := exec.Command("cat", "-") 
    stdin, _ := cmd.StdinPipe() 
    stdout, _ := cmd.StdoutPipe() 

    cmd.Start() 
    io.WriteString(stdin, "Hello world!") 

    stdin.Close(); 
    output, _ := ioutil.ReadAll(stdout) 

    fmt.Println(string(output)) 
} 
+1

필자의 예는 간결함을 위해 일회적 인 주요 기능이었다. 실제 코드에서는 오류를 무시할 수 없습니다. –

+0

간결함은 대답을 완전히 바꿀 수 있습니다. 코드가 실제로 main을 대상으로한다면, 에러가 발생할 때'log.Fatal'을 사용하는 것이 적합 할 것입니다. RPC 호출의 일부인 경우 오류를 래핑하고 다른 유용한 정보를 첨부해야합니다 (실패 할 경우 우리가 가지고있는 것을 제공해야합니까?). 내 의견에 초점을 맞 춥니 다. '오류를 반환합니다. 응용 프로그램 내에서 호출의 컨텍스트와 관련된 몇 가지 추가 정보를 사용하여 오류를 래핑하여 추가로 처리 할 수 ​​있습니다.'오류를 무시한 코드 샘플은 사후에 고려해야 할 사항이며 그. – dskinner

-3

이와 같은 상황에서, 나는 보통 조금 밖으로 평평하게합니다.

func myFunc() (err error) { 
    cmd := exec.Command("cat", "-") 

    stdin, err := cmd.StdinPipe();     if err != nil { return } 
    stdout, err := cmd.StdoutPipe();     if err != nil { return } 

     err = cmd.Start();       if err != nil { return } 
    _, err = io.WriteString(stdin, "Hello world!"); if err != nil { return } 
     err = stdin.Close();       if err != nil { return } 
    o, err := ioutil.ReadAll(stdout);    if err != nil { return } 

    fmt.Println(string(o)) 
    return 
} 

여전히 못생긴하지만 적어도 수직적이지는 않습니다.

나는 모든 종류의 관습에 순응한다고 말할 수는 없지만 IMO를 읽는 것이 훨씬 쉽습니다.

+12

'gofmt'를 코드에 처음 적용하면 서식이 파기됩니다. – peterSO

0

나는 Go에 몇백 줄을 썼다. 그래서 나는 어떤 관용적 인 방법을 나타내는 제목이 없다. 그러나 반복적 인 호출 및 점검 오류 단계의 경우, 논리를 되돌리려면 코드를 작성하고 읽는 것이 더 쉽다는 것을 알았습니다. 종료 조건을 점검하는 대신 오류가 발생했습니다 (오류! = nil), 나는 계속하기위한 조건을 점검한다. (err == nil).
발신자에게 반송하거나 인쇄/로깅하는 것과 같은 오류를 처리 할 수있는 고유 한 방법이있는 경우이 작업을 수행 할 수 있습니다. 이 접근법의 단점은 할당 된 if 블록의 범위를 가지므로 =를 사용하여 변수를 암시 적으로 선언 할 수 없다는 것입니다.

func main() { 
    var output []byte 
    var stdin io.WriteCloser 
    var stdout io.Reader 

    cmd := exec.Command("cat", "-") 

    stdin, err := cmd.StdinPipe() 

    if err == nil { 
     stdout, err = cmd.StdoutPipe() 
    } 

    if err == nil { 
     err = cmd.Start() 
    } 

    if err == nil { 
     _, err = io.WriteString(stdin, "Hello world!") 
    } 

    if err == nil { 
    output, err = ioutil.ReadAll(stdout) 
    } 

    if err == nil { 
    err = stdin.Close(); 
    } 

    if err == nil { 
      fmt.Println(string(output)) 
    } else { 
     fmt.Println(string(err.Error())) // Error handling goes here 
    } 

    return 
} 
관련 문제