go generate 생성 코드

6275 단어
앞으로 한동안 go generate를 연구해야 하고, 홈페이지 블로그에서 롭 픽이 쓴 generating code를 보면서 번역하는 데 시간이 좀 걸렸다.몇 개의 문장이 정확하게 번역되었는지 고려해야 하니, 바로잡아 주십시오.

코드 생성


유니버설 컴퓨팅의 특징 - 그래픽 완비 - 컴퓨터 프로그램으로 컴퓨터 프로그램을 작성할 수 있습니다.자주 나타나지만 완벽하지는 않다는 강력한 생각이다.예를 들어 이것은 컴파일러 정의의 중요한 구성 부분이다.그것 또한 gotest 명령의 작업 원리이다. 테스트할 소프트웨어 패키지를 스캔하여 패키지의 맞춤형 테스트 도구를 포함하는 Go 프로그램을 작성한 다음 컴파일하고 실행한다.현대 컴퓨터는 비싸 보이는 이 서열을 몇 분의 1초에 완성할 수 있을 정도로 빠르다.
프로그램 작성자의 다른 예도 많다.예를 들어 야cc는 문법 설명을 읽고 프로그램을 써서 이 문법을 해석한다.Protocol buffer "컴파일러"는 인터페이스 설명 출력 구조 정의, 방법 및 기타 지원 코드를 읽습니다.각종 설정 도구도 이렇게 작동한다. 메타데이터나 환경을 검사하고 사용자 정의 로컬 설정을 출력한다.
따라서 프로그램을 작성하는 프로그램은 소프트웨어 공학의 중요한 구성 부분이지만yacc와 같이 원본 코드를 생성할 수 있는 프로그램은 그들의 출력을 컴파일할 수 있도록 구축 과정에 기초를 두어야 한다.Make와 같은 외부 구축 도구를 사용할 때, 이것은 보통 쉽게 할 수 있다.그러나 Go에서 Go의 도구는 Go 원본에서 필요한 구축 정보를 모두 얻는 데 문제가 있다.go tool에서 야cc를 단독으로 실행할 수 있는 메커니즘이 없습니다.
지금까지, 그렇습니다.
최신 Go 릴리스 1.4에는 도구를 보다 쉽게 실행할 수 있는 새로운 명령이 포함되어 있습니다.이것은 go generate라고 하는데, Go 원본의 특수 주석을 스캔해서 실행할 일반 명령을 식별할 수 있다.go generate가 go build의 일부분이 아니라는 것을 이해하는 것이 중요하다.이것은 의존 관계 분석을 포함하지 않습니다. gobuild을 실행하기 전에 현시적으로 실행해야 합니다.클라이언트가 아닌 Go package 작성자가 사용하도록 설계되었습니다.
Go generate 명령은 사용하기 쉽습니다.예열로서 야cc 문법을 만드는 데 어떻게 사용하는지 보여 줍니다.가령 당신에게 gopher라는 이름이 있다면.y의 YACC 입력 파일은 새로운 언어의 구문을 정의합니다.구문을 구현하는 Go 소스 파일을 생성하려면 일반적으로 Yacc의 표준 Go 버전이 호출됩니다.
go tool yacc -o gopher.go -p parser gopher.y

-o 옵션 명령 출력 파일, -p 옵션은 패키지 이름을 지정합니다.
go generate에서 이 과정을 구동하려면 같은 디렉터리에 있는 모든 일반 (비생성) 을 사용하십시오.go 파일에서 주석을 추가한 파일의 모든 위치:
//go:generate go tool yacc -o gopher.go -p parser gopher.y

이 텍스트는 위의 명령입니다. 앞에 go generate가 식별하는 특수한 주석을 붙입니다.주석은 줄의 시작부터 시작해야 하며//와 go:generate 사이에 빈칸이 없어야 합니다.이 표시 다음에, 이 줄의 나머지 부분은 go generate가 실행하는 명령을 지정합니다.
지금 그것을 운행합니다.원본 디렉터리로 전환하고 gogenerate를 실행한 다음 gobuild 등등을 실행합니다.
$ cd $GOPATH/myrepo/gopher
$ go generate
$ go build
$ go test

 
만약 오류가 없다면, go generate 명령은 yacc를 호출해서 gopher를 만들 것입니다.go 파일, 이 디렉터리는 완전한 go 원본 파일을 포함하기 때문에 우리는 정상적으로 구축하고 테스트하며 정상적으로 작업할 수 있습니다.매번 gopher.gogenerate를 다시 실행해서 해상도를 다시 생성하기만 하면 gogenerate가 수정됩니다.
gogenerate가 어떻게 작동하는지에 대한 더 자세한 정보는 옵션, 환경 변수 등을 포함하여 디자인 문서를 참조할 수 있습니다.
Go generate는 make나 다른 컴파일 메커니즘에 영향을 주지 않지만, go tool을 따르기 때문에 추가 설치가 필요 없고 Go 생태계에 적합하다.클라이언트가 아닌 패키지 작성자라는 것을 기억하십시오. 단지 호출된 프로그램이 대상 기기에서 사용할 수 없기 때문입니다.또한 goget을 통해 패키지를 가져오면 파일이 생성되고 테스트되면 클라이언트가 사용할 수 있도록 원본 라이브러리에 체크 인해야 합니다.
이제 go generate가 생겨서 그것으로 새로운 일을 할 수 있다.gogenerate를 어떻게 사용하는지 심상치 않은 예로 새로운 프로그램golang이 있습니다.org/x/tools 창고를stringer라고 합니다.그것은 자동으로 정수 상수 집합을 위한 문자열 방법을 작성할 수 있다.그것은 발행판의 일부분은 아니지만, 설치하기 쉽다.
$ go get golang.org/x/tools/cmd/stringer

 
Stringer 문서에는 여러 유형의 성형 상수를 정의하는 그룹을 포함하는 예가 있습니다.
 
 
package painkiller
 
type Pill int
 
const (
    Placebo Pill = iota
    Aspirin
    Ibuprofen
    Paracetamol
    Acetaminophen = Paracetamol
)
 
디버깅을 위해서, 우리는 변수가 자신을 잘 인쇄하기를 희망한다. 이것은 다음과 같은 서명을 가진 방법이 필요하다는 것을 의미한다.
 
func (p Pill) String() string
 
손으로 쓰는 것은 매우 쉽다. 아마도 다음과 같다.
func (p Pill) String() string {
    switch p {
    case Placebo:
        return "Placebo"
    case Aspirin:
        return "Aspirin"
    case Ibuprofen:
        return "Ibuprofen"
    case Paracetamol://== Acetaminophen
        return "Paracetamol"
    }
    return fmt.Sprintf("Pill(%d)", p)
}
 
물론 이 기능을 쓰는 다른 방법도 있다.우리는 Pill 인덱스 문자열이나 맵, 또는 다른 기술을 사용할 수 있습니다.우리가 무엇을 하든지, 만약 우리가 Pills 집합을 바꾸면, 우리는 그것이 정확하다는 것을 보장하기 위해 그것을 유지해야 한다.(Paracetamol의 Name 두 개가 다른 것보다 까다롭다.)또한 어떤 방법을 취하느냐의 문제는 유형과 값에 달려 있다. 기호가 있느냐 없느냐, 밀집하느냐, 희소하느냐, 0을 바탕으로 하느냐, 0을 바탕으로 하지 않느냐 등이다.
 
Stringer 프로그램은 모든 세부 사항을 처리합니다.독립적으로 실행할 수 있지만 gogenerate에서 구동합니다. 원본 코드에 주석을 추가하고 형식 정의 근처에 주석을 만들 수 있습니다.
//go:generate stringer -type=Pill
 
이 규칙은 go generate에서 stringer 도구를 실행하여 Pill 유형의 String 방법을 생성합니다.출력은 자동으로 pill 에 기록됩니다.string.go (기본적으로, 우리는 -output 로고를 사용하여 덮어쓸 수 있습니다)
실행 후
$ go generate
$ cat pill_string.go
//generated by stringer -type Pill pill.go; DO NOT EDIT
 
package pill
 
import "fmt"
 
const _Pill_name = "PlaceboAspirinIbuprofenParacetamol"
 
var _Pill_index = [...]uint8{0, 7, 14, 23, 34}
 
func (i Pill) String() string {
    if i < 0 || i+1 >= Pill(len(_Pill_index)) {
        return fmt.Sprintf("Pill(%d)", i)
    }
    return _Pill_name[_Pill_index[i]:_Pill_index[i+1]]
}
$
Pill이나 상수의 정의를 변경할 때마다 Go generate를 실행하여 String 방법을 업데이트해야 합니다.물론, 만약 우리가 같은 가방에 여러 종류로 이런 방식을 설정했다면, 하나의 명령으로 모든 String 방법을 업데이트할 수 있다.
의심할 여지없이 생성 방법은 추하다.그러나 그것은 받아들일 수 있다. 왜냐하면 인간은 그것과 관련된 일을 할 필요가 없기 때문에 기계가 생성한 코드는 보통 추하기 때문이다.그것은 고효율을 위해 노력한다.모든 이름이 하나의 문자열에 있기 때문에 메모리를 절약할 수 있다. (수십 개가 있어도 하나의 문자열 헤더만 있다.)그리고 하나의 수조,Pill_index, 값에서 이름으로 간단하고 효율적인 기술을 사용합니다.주의하세요,Pill_index는 uint8의 그룹 (슬라이드가 아닌) 이며, 값 공간을 충분히 뛰어넘는 최소 정수입니다.더 많은 값이나 더 적은 값이 있다면 생산의Pill_index 형식이 uint16 또는 int8로 바뀔 수 있습니다.무엇이든지 효과가 좋다.
Stringer에서 생성한 Method에서 사용하는 방법은 상수 집합의 속성에 따라 달라집니다.예를 들어 상수가 희소하면 맵을 사용할 수 있습니다.다음은 상수 집합을 바탕으로 하는 흔한 예로 또 다른 것을 대표한다.
 
const _Power_name = "p0p1p2p3p4p5..."
 
var _Power_map = map[Power]string{
    1:    _Power_name[0:2],
    2:    _Power_name[2:4],
    4:    _Power_name[4:6],
    8:    _Power_name[6:8],
    16:   _Power_name[8:10],
    32:   _Power_name[10:12],
    ...,
}
 
func (i Power) String() string {
    if str, ok := _Power_map[i]; ok {
        return str
    }
    return fmt.Sprintf("Power(%d)", i)
}
요컨대 자동적으로 생성된method는 인간보다 더 잘할 수 있다.
go tree에 go generate의 많은 다른 용도가 설치되어 있습니다.유니버설 패키지에서 유니버설 테이블을 생산하고 encoding/gob에 효과적인 코딩 방법을 만들며 타임 패키지에서 시간대 데이터를 만드는 등등을 포함한다.
go generate를 창조적으로 사용하고 실천을 격려하세요.
 
없더라도 새 stringer 도구를 사용하여 성형 상수에 대한 String 방법을 작성합니다.기계로 하여금 이런 일을 하게 하다.
 
By Rob Pike
전재 대상:https://www.cnblogs.com/majianguo/p/6653919.html

좋은 웹페이지 즐겨찾기