io가 뭐예요?Go의 리더?

19087 단어 gocodenewbie
만약 네가 바둑 프로그램을 쓴다면, 너는 io.Reader 인터페이스를 상당히 많이 만날 것이다.그것은 많은 다른 출처에서 읽은 데이터를 나타내는 데 광범위하게 사용되지만, 그 유형의 정의는 사실상 상당히 간단하다.
type Reader interface {
    Read(p []byte) (n int, err error)
}
오직 한 가지 방법!이것은 Read라는 방법으로 형식을 생성하고 바이트를 받아들여 int에 발생한 오류를 되돌려준다면 형식은 io.Reader 이라는 것을 의미합니다.그러나 이 인터페이스의 생각은 무엇입니까? 우리는 어떻게 코드에서 그것을 사용합니까?

함수 서명 봐.

Reader는 강력한 추상적인 작은 인터페이스입니다!그 추상은 도대체 무엇입니까?Read 방법의 사상은 어떤 원본에서 데이터 바이트를 읽으면 코드에서 이 바이트를 사용할 수 있다는 것을 나타낸다.이 출처는 파일, 카메라, 네트워크 연결일 수도 있고, 일반적인 오래된 문자열일 수도 있다.예를 들어 파일에서 데이터를 읽으면 io.Reader*os.File 입니다.
시도하기 전에 Reader.Read 함수 서명 부분을 살펴보겠습니다.
Read(p []byte) (n int, err error)
  • p []byte는 우리가 읽는 방법에 전달하는 바이트이다.판독기는 파일 같은 데이터 원본에서 읽은 데이터를 이 바이트로 복사합니다.
  • 되돌아오는 n intRead 호출에서 몇 바이트를 읽었는지 알려 줍니다.
  • 되돌아오는 err error 은 데이터를 읽을 때 발생할 수 있는 모든 오류입니다. 예를 들어 파일 끝에 도달하는 것입니다.
  • 우리가 그것을 어떻게 사용하는지 파일로 시도해 봅시다.이 텍스트를 복사하여 sloth.txt 라는 새 디렉토리의 파일에 저장합니다.
    I'm a sloth and hibiscus flowers are tasty!
    
    이제 Go 코드를 작성하여 파일을 읽는 방법을 사용합니다.이 코드를 복사해서 sloth가 있는 디렉터리에 있는 파일 main.go 에 저장합니다.txt:
    package main
    
    import (
        "log"
        "os"
    )
    
    func main() {
        file, err := os.OpenFile("sloth.txt")
        if err != nil {
            log.Fatalf("error opening sloth.txt: %v", err)
        }
        defer file.Close()
    
        // Make a byte slice that's big enough to store a few words of the message
        // we're reading
        bytesRead := make([]byte, 33)
    
        // Now read some data, passing in our byte slice
        n, err := file.Read(bytesRead)
        if err != nil {
            log.Fatalf("error reading from sloth.txt: %v", err)
        }
    
        // Take a look at the bytes we copied into the byte slice
        log.Printf("We read \"%s\" into bytesRead (%d bytes)",
            string(bytesRead), n)
    }
    
    go run main.go 명령을 실행하면 다음과 같은 출력을 얻을 수 있습니다.
    We read "I'm a sloth and hibiscus flowers " (33 bytes) into bytesRead
    
    따라서 Go 는 호출 os.File.Read 시 파일에서 데이터를 읽어 bytesRead 로 복사합니다. 오류가 발생하지 않았기 때문에 0 으로 되돌아옵니다.우리는bytesRead 부분을 Read 함수에 전달할 것입니다. 마치 우리가 컵을 사이다 분수에 전달하는 것처럼!

    이것이 바로 우리가 바이트를 얻는 방식이지만, 왜 우리는 심지어 읽은 바이트 수를 되돌려줍니까?
    원인을 알아보기 위해 우리가 다시 전화를 걸면 Read 무슨 일이 일어날지 봅시다.우리는 나무늘보가 부용화에 대한 견해를 보고 싶다!주 함수의 끝에 추가:
        n, err = file.Read(bytesRead)
        if err != nil {
            log.Fatalf("error reading from sloth.txt: %v", err)
        }
    
        log.Printf("We read \"%s\" into bytesRead (%d bytes)",
            string(bytesRead), n)
    
    현재 go run main.go 의 출력은 다음과 같습니다.
    2020/03/01 13:38:50 We read "I'm a sloth and hibiscus flowers " into bytesRead (33 bytes)
    2020/03/01 13:38:50 We read "are tasty!
     and hibiscus flowers " into bytesRead (11 bytes)
    
    예상대로 우리는 책에서 우리의 나무늘보가 확실히 부용화를 좋아하지만, 왜 우리가 수출한 세 번째 줄설and hibiscus flowers을 읽었다.
    왜냐하면 우리의 리더가 파일에 남은 11바이트를 우리의 bytesRead 슬라이스의 시작 부분에 복사했을 때, 슬라이스의 나머지 부분에 닿지 않았기 때문이다.슬라이스의 나머지 부분은 우리가 지난번 호출 Read 때 읽은 바이트를 포함합니다!

    따라서 되돌아오는 정수 n 는 바이트에 우리가 읽은 내용을 포함하는 바이트를 알려준다.이렇게 하면 이 바이트를 처리하는 코드는 영화의 어떤 바이트에 관심을 가져야 하는지, 어떤 바이트에 관심을 가져야 하는지 알게 될 것이다.

    io 오류 처리.독자


    다시 한 번 전화해 봅시다file.Read:
        n, err = file.Read(bytesRead)
        if err == io.EOF {
            log.Printf("End of file reached; we got %d bytes on the last read", n)
        } else {
            log.Fatalf("unexpected error reading from the file: %v\n", err)
        }
    
    go run main.go를 사용하여 다음 명령을 실행합니다.
    2020/03/01 13:44:35 We read "I'm a sloth and hibiscus flowers " into bytesRead (33 bytes)
    2020/03/01 13:44:35 We read "are tasty!
     and hibiscus flowers " into bytesRead (11 bytes)
    2020/03/01 13:44:35 End of file reached; we got 0 bytes on the last read
    
    우리가 얻은 오류는 io.EOF 로'파일이 끝났다'는 것을 대표한다. 이것은 우리가 통상적으로 기대하는 오류이다.EOF를 만났을 때, 코드가 읽은 바이트를 처리하고 이 io에서 데이터를 읽는 것을 멈추는 것이 일반적입니다.데이터가 없으니까.
    그러나 EOF는 io.Reader.Read 에서 반환할 수 있는 유일한 오류가 아닙니다.만약 우리가 EOF 이외의 오류를 얻게 된다면, 통상적으로 코드에 오류가 있거나, 의외의 일이 발생했다는 것을 의미한다.예를 들어, 이 코드를 close-early.go 로 복사하여 닫힌 파일에서 읽으려면 다음과 같이 하십시오.
    package main
    
    import (
        "log"
        "os"
    )
    
    func main() {
        file, err := os.OpenFile("sloth.txt")
        if err != nil {
            log.Fatalf("error opening sloth.txt: %v", err)
        }
        file.Close()
    
        bytesRead := make([]byte, 0, 33)
        if _, err := file.Read(bytesRead); err != nil {
            log.Fatalf("error reading from sloth.txt: %#v", err)
        }
    }
    
    go run close-early.go를 사용하여 실행할 경우 다음을 수행해야 합니다.
    2020/03/01 13:45:45 error reading from sloth.txt: &os.PathError{Op:"read", Path:"sloth.txt",
      Err:(*errors.errorString)(0xc000010110)}
    exit status 1
    
    닫힌 파일을 읽으려고 시도하고 있기 때문에 os.PathError따라서 일반적으로 실행 중인 경우io.Reader.Read
  • ✅ 만약 우리가 제로 오류를 얻게 된다면, 우리의 코드는 리더에서 bytesRead[:n] 바이트로 복사되어 더 많은 데이터를 계속 읽을 수 있습니다.
  • 🛑 만약 우리가 io.EOF 을 얻게 된다면, 우리는 데이터 읽기를 멈춰야 합니다. 만약 어떤 바이트가 bytesRead 로 복사된다면, 우리는 당신의 코드 처리 n 의 마지막 bytesRead[:n] 바이트를
  • ⚠️ 만약 우리가 또 다른 잘못을 만났다면, 이것은 의외일 수도 있다.만약 어떤 바이트를 읽었다면, 코드를 처리한 다음, 당신이 적절하다고 생각하는 오류로 논리적으로 오류를 처리합니다.
  • 비록 우리가 제로 오류가 아니더라도, 우리는 우리가 사용할 수 있는 코드 중의 일부 바이트를 성공적으로 읽을 수 있기 때문에, io.Reader 을 사용하는 코드는 통상적으로 이 바이트를 처리해야 한다.

    io에 구축합니다.독자

    io.Reader.Read는 대량의 데이터 원본에서 데이터를 읽는 일반적인 방법을 제공하지만, Go 프로젝트에서는 일반적으로 직접 호출하지 않습니다Read.반대로 우리는 이 방법 위에 구축된 코드가 있다.그 중 일부는 다음과 같습니다.
  • 원본의 모든 바이트를 긴 바이트 필름에 읽으려면 탐색기를 ioutil.ReadAll에 전달할 수 있습니다!
  • 만약 당신이 한 줄씩 파일을 읽고 싶다면, 그 bufio.Scanner 방법으로 한 줄의 데이터를 읽을 수 있고, 스캐너는 새로운 줄을 찾는 작업을 처리할 것이다. 그러면 당신의 코드는 당신을 위해 이 점을 고려할 필요가 없다.
  • 이미지 데이터 처리?이 패키지는 그림을 특이한 Scan 인터페이스로 디코딩하는 데 도움을 줄 것입니다!
  • 웹 응용 프로그램을 위해 JSON에서 데이터를 반서열화합니까?image.Image"JSON 논리가 이미 포함되어 있습니다!
  • 왜 이 코드만 사용하고 사용하지 않습니까json.Decoder.Decode?Read는 저급 인터페이스이기 때문이다.원본에서 데이터를 읽고 바이트로 복사하는 작업이지만, 어떤 바이트를 읽었는지는 상관없습니다.실제로 이 바이트를 처리하는 것은 Read를 호출하는 코드로 처리됩니다.
    이 점을 보려면 JSON을 반서열화해봅시다!이 Go 코드를 에 저장하기io.Reader:
    package main
    
    import (
        "encoding/json"
        "fmt"
        "strings"
    )
    
    type AnimalFacts struct {
        CommonName     string   `json:"commonName"`
        ScientificName string   `json:"scientificName"`
        HeightInInches int      `json:"heightInInches"`
        FavoriteFoods  []string `json:"favoriteFoods"`
        CanSwim        bool     `json:"canSwim"`
    }
    
    func main() {
        jsonData := `
    {
        "commonName":     "brown-throated three-toed sloth",
        "scientificName": "Bradypus variegatus",
        "heightInInches": 31,
        "favoriteFoods":  ["Cecropia leaves", "Hibiscus flowers"],
        "canSwim":        true
    }`
    
        // an io.Reader that isn't a file!
        rdr := strings.NewReader(jsonData)
    
        var sloth AnimalFacts
        if err := json.NewDecoder(rdr).Decode(&sloth); err != nil {
            fmt.Printf("error deserializing JSON: %v", err)
            return
        }
    
        fmt.Printf("Hi! I'm a %s (%s)! I'm about %d\" tall, and love eating %v!\n",
            sloth.CommonName, sloth.ScientificName, sloth.HeightInInches,
            sloth.FavoriteFoods)
        if sloth.CanSwim {
            fmt.Println("By the way, I can swim!")
        }
    }
    
    sloth-facts.go를 사용하여 이 명령을 실행하면 다음과 같은 출력을 얻을 수 있습니다.
    Hi! I'm a brown-throated three-toed sloth (Bradypus variegatus)! I'm about 31"
    tall, and love eating [Cecropia leaves Hibiscus flowers]!
    By the way, I can swim
    
    여기서 무슨 일이 일어났습니까?
  • 문자열에서 JSON 데이터를 가져와서 그것으로 go run sloth-facts.go 을 생성합니다.파일을 io로 사용하는 것이 아니라독자, 우리는 일반적인 낡은 문자열에서 데이터를 읽을 수 있도록 io.Reader 을 만들고 있습니다!
  • strings.Reader 수용json.NewDecoder, 그래서 문자열을 전달합니다.리더는 JSON 데이터를 리더에서 읽는 구조를 설정하고 Go 변수로 들어갑니다.
  • 우리는 io.Reader 구조를 가리키는 바늘을 json.Decoder에 전달하고 우리의 JSON 데이터는 이 구조에 읽힌다!
  • 우리는 귀여운 나무늘보 사실 정보에서 우리의 데이터를 출력하여 동물원 관리자가 나무늘보 전람회에 표지를 붙이도록 준비한다!
  • 만약 우리가 AnimalFacts에 대한 간단한 조정을 통해 JSON 데이터를 읽는다면, 우리는 괄호와 쉼표, 그리고 우리가 현재 JSON에 있는 필드 등을 추적해야 한다.하지만 json.Decoder.Decode Go팀은 이미 우리를 위해 이 문제를 해결했고 io.Reader.Read을 바탕으로 JSON 디코딩 논리를 구축했다!
    보시다시피 json.Decoder.Decode 은 진정한 다기능 인터페이스입니다!이것이 바로 Go 코드에서 곳곳에서 볼 수 있는 이유입니다Read. io.Reader 방법과 함께 작업하는 코드로 모든 데이터 형식을 처리할 수 있습니다. 이것은 훌륭한 Go 인터페이스 추상입니다!

    좋은 웹페이지 즐겨찾기