효과적인 Go

Jmnote (토론 | 기여)님의 2024년 9월 28일 (토) 15:31 판 (→‎new로 할당)

1 개요

Crystal Clear action info.png 작성 중인 문서입니다.
Effective Go
이펙티브 Go, 효과적인 Go

https://go.dev/doc/effective_go

2 소개

Go는 새로운 언어입니다. 기존 언어에서 아이디어를 차용했지만, 효과적인 Go 프로그램은 기존 언어로 작성된 프로그램과 성격이 다릅니다. C++ 또는 Java 프로그램을 Go로 직접 번역하는 것은 만족스러운 결과가 되지 못할 가능성이 큽니다. Java 프로그램은 Java로 작성되어야지 Go로 작성되지 않습니다. 반면, Go의 관점에서 문제를 생각하면 성공적이지만 상당히 다른 프로그램을 만들 수 있습니다. 즉, Go를 잘 작성하려면 Go의 속성과 관용구를 이해하는 것이 중요합니다. 또한, 이름 지정, 포맷팅, 프로그램 구성 등 Go 프로그래밍의 기존 규칙을 아는 것도 중요합니다. 그래야 작성한 프로그램이 다른 Go 프로그래머에게 쉽게 이해될 수 있습니다.

이 문서는 명확하고 관용적인 Go 코드를 작성하기 위한 팁을 제공합니다. 언어 사양, Go 투어, Go 코드 작성 방법과 같은 문서를 먼저 읽은 후 보충 자료로 활용하시기 바랍니다.

2022년 1월 추가사항: 이 문서는 2009년 Go의 출시를 위해 작성되었으며, 그 이후로 크게 업데이트되지 않았습니다. 언어 자체를 이해하는 데는 좋은 가이드이지만, 언어의 안정성 덕분에 라이브러리에 대해 거의 언급하지 않으며, 빌드 시스템, 테스트, 모듈, 다형성 등 Go 생태계의 중요한 변화에 대해서는 아무런 언급이 없습니다. 너무 많은 변화가 있었고, 현대 Go 사용법을 잘 설명하는 많은 문서, 블로그, 책들이 존재하기 때문에 이 문서를 업데이트할 계획은 없습니다. 효과적인 Go는 여전히 유용하지만, 독자는 이 문서가 완전한 가이드가 아님을 이해해야 합니다. 자세한 내용은 이슈 28782를 참조하세요.

2.1 예시

Go 패키지 소스는 핵심 라이브러리 역할뿐만 아니라 언어 사용 예시로도 활용될 수 있도록 작성되었습니다. 또한, 많은 패키지에는 go.dev 웹사이트에서 직접 실행할 수 있는 작동가능한 자체 포함 실행 예제가 포함되어 있습니다. (필요한 경우 "Example"이라는 단어를 클릭하여 엽니다.) 문제를 해결하는 방법이나 특정 기능 구현 방법에 대해 궁금한 점이 있다면, 라이브러리의 문서, 코드 및 예제가 답변, 아이디어, 배경을 제공할 수 있습니다.

3 포맷팅

4 주석

5 이름

5.1 패키지 이름

5.2 게터

5.3 인터페이스 이름

5.4 MixedCaps

6 세미콜론

7 제어 구조

7.1 If

7.2 재선언과 재할당

7.3 For

7.4 Switch

7.5 타입 switch

8 함수

8.1 멀티 반환 값

8.2 명명된 결과 파라미터

8.3 Defer

9 데이터

9.1 new로 할당

Go에는 메모리를 할당하는 두 가지 기본 기능인 newmake가 있습니다. 이 둘은 서로 다른 일을 수행하며 다른 타입에 적용되기 때문에 헷갈릴 수 있지만, 그 규칙은 간단합니다. 먼저 new에 대해 알아보겠습니다. new는 메모리를 할당하는 빌트인 함수이지만, 다른 언어의 이름과 비슷한 기능들과는 달리 메모리를 초기화하지 않고, 단지 제로로 설정만 합니다. 즉, new(T)는 타입 T의 새 항목을 위한 제로로 채워진 저장 공간을 할당하고 해당 주소를 반환하며, 이는 *T 타입의 값이 됩니다. Go 용어로, 이는 타입 T의 새로 할당된 제로값에 대한 포인터를 반환합니다.

new에 의해 반환된 메모리가 제로로 설정되기 때문에, 데이터 구조를 설계할 때 각 타입의 제로값을 추가 초기화 없이 사용할 수 있도록 배열하는 것이 유용합니다. 이렇게 하면 데이터 구조의 사용자가 new를 사용하여 하나를 생성하고 바로 사용할 수 있습니다. 예를 들어, bytes.Buffer의 문서는 "Buffer의 제로값은 사용 가능한 빈 버퍼입니다."라고 설명하고 있습니다. 마찬가지로 sync.Mutex는 명시적인 생성자나 Init 메서드가 없습니다. 대신, sync.Mutex의 제로값은 잠금 해제된 뮤텍스로 정의됩니다.

제로값이 유용하다는 특성은 전이적으로 적용됩니다. 다음 타입 선언을 살펴보세요.

type SyncedBuffer struct {
    lock    sync.Mutex
    buffer  bytes.Buffer
}

SyncedBuffer 타입의 값들은 할당되거나 선언된 직후에 바로 사용할 준비가 되어 있습니다. 다음 코드 스니펫에서 pv 모두 추가 작업 없이 올바르게 작동합니다.

p := new(SyncedBuffer)  // 타입: *SyncedBuffer
var v SyncedBuffer      // 타입:  SyncedBuffer

9.2 생성자와 복합 리터럴

9.3 make로 할당

9.4 배열

9.5 슬라이스

9.6 2차원 슬라이스

9.7

9.8 출력

9.9 덧붙이기

10 초기화

10.1 상수

10.2 변수

10.3 init 함수

11 메소드

11.1 포인터 vs 값

12 인터페이스와 기타 타입

12.1 인터페이스

12.2 변환

12.3 인터페이스 변환과 타입 어썰션

12.4 일반성

12.5 인터페이스와 메소드

13 빈 식별자

13.1 멀티 할당에서 빈 식별자

13.2 미사용 임포트와 변수

13.3 사이드 이펙트용 임포트

13.4 인터페이스 체크

14 임베딩

15 동시성

15.1 통신으로 공유

15.2 고루틴

15.3 채널

15.4 채널의 채널

15.5 병렬화

15.6 누수 버퍼

16 오류

16.1 패닉

16.2 복구

17 웹 서버

이제 Go 프로그램을 완성해 봅시다. 이번에는 웹 리-서버(web re-server)입니다. Google은 chart.apis.google.com에서 데이터를 차트와 그래프로 자동으로 포맷팅하는 서비스를 제공합니다. 그러나 이 서비스를 상호작용적으로 사용하기는 어렵습니다. 왜냐하면 데이터를 쿼리로 URL에 넣어야 하기 때문입니다. 여기서 제공되는 프로그램은 한 가지 형태의 데이터에 대해 더 나은 인터페이스를 제공합니다. 짧은 텍스트 조각을 입력하면, 이 프로그램은 QR 코드(텍스트를 인코딩하는 상자의 매트릭스)를 생성하기 위해 차트 서버를 호출합니다. 이 이미지는 휴대전화의 카메라로 잡아 URL로 해석할 수 있으며, 이를 통해 휴대전화의 작은 키보드에 URL을 입력하는 수고를 덜 수 있습니다.

다음은 Go로 작성된 웹 서버 프로그램입니다:

package main

import (
    "flag"
    "html/template"
    "log"
    "net/http"
)

var addr = flag.String("addr", ":1718", "http service address") // Q=17, R=18

var templ = template.Must(template.New("qr").Parse(templateStr))

func main() {
    flag.Parse()
    http.Handle("/", http.HandlerFunc(QR))
    err := http.ListenAndServe(*addr, nil)
    if err != nil {
        log.Fatal("ListenAndServe:", err)
    }
}

func QR(w http.ResponseWriter, req *http.Request) {
    templ.Execute(w, req.FormValue("s"))
}

const templateStr = `
<html>
<head>
<title>QR Link Generator</title>
</head>
<body>
{{if .}}
<img src="http://chart.apis.google.com/chart?chs=300x300&cht=qr&choe=UTF-8&chl={{.}}" />
<br>
{{.}}
<br>
<br>
{{end}}
<form action="/" name=f method="GET">
    <input maxLength=1024 size=70 name=s value="" title="Text to QR Encode">
    <input type=submit value="Show QR" name=qr>
</form>
</body>
</html>
`


main 함수까지는 쉽게 따라올 수 있습니다. 이 플래그는 서버의 기본 HTTP 포트를 설정합니다. 템플릿 변수인 templ부터 재미있어 집니다. 이 변수는 HTML 템플릿을 빌드하여 서버가 페이지를 표시할 때 실행하게 합니다. 이에 대해서는 잠시 후에 더 자세히 설명하겠습니다.

main 함수는 플래그를 해석하고, 앞서 언급한 메커니즘을 사용하여 QR 함수를 서버의 루트 경로에 바인딩합니다. 그런 다음 http.ListenAndServe를 호출하여 서버를 시작합니다. 이 함수는 서버가 실행되는 동안 블록됩니다.

QR 함수는 요청을 수신하고, 요청에는 폼 데이터가 포함되며, 폼 값에 있는 데이터를 사용하여 템플릿을 실행합니다.

템플릿 패키지인 html/template은 강력합니다. 이 프로그램은 그 기능의 일부분만 다룹니다. 본질적으로, templ.Execute에 전달된 데이터 항목에서 파생된 요소를 대체함으로써 HTML 텍스트의 일부를 동적으로 재작성합니다. 템플릿 텍스트(templateStr) 내에서 중괄호 두 개로 구분된 부분은 템플릿 동작을 나타냅니다. {{if .}}에서 {{end}}까지의 부분은 현재 데이터 항목의 값이 비어 있지 않은 경우에만 실행됩니다. 즉, 문자열이 비어 있을 때는 이 템플릿의 일부가 억제됩니다.

{{.}}이라는 두 개의 스니핏은 템플릿에 제공된 데이터, 즉 쿼리 문자열을 웹 페이지에 표시하라는 의미입니다. HTML 템플릿 패키지는 자동으로 적절한 이스케이프 처리를 제공하여 텍스트가 안전하게 표시되도록 합니다.

템플릿 문자열의 나머지 부분은 페이지가 로드될 때 표시할 HTML입니다. 이 설명이 너무 빠르면 template 패키지의 문서를 참조하여 더 자세한 설명을 확인하십시오.

이제 몇 줄의 코드와 일부 데이터 기반 HTML 텍스트로 유용한 웹 서버를 만들 수 있습니다. Go 언어는 몇 줄의 코드로 많은 일을 할 수 있을 만큼 강력합니다.

18 같이 보기

19 참고

문서 댓글 ({{ doc_comments.length }})
{{ comment.name }} {{ comment.created | snstime }}