Search
Duplicate

go언어 정리중

수업
Tucker의 Go
주제
5 more properties

Go CLI

# go 소스코드를 컴파일하여 실행 가능한 바이너리 생성 go build # go 소스코드를 컴파일하고 즉시 실행 go run # _test.go 로 끝나는 파일을 찾아 내장 테스트 프리엠워크 실행 go test # 외부 패키지나 라이브러리를 다운로드하고 설치, go.mod 파일을 업데이트 go get # Go 모듈을 관리하는데 사용한다. go mod go mod init # 새로운 모듈 초기화 # 소스 코드를 go의 표준 포맷팅으로 자동정렬 go fmt # Go의 환경변수 출력 go env # 코드에서 일반적인 오류를 찾기위한 정적 분석 go vet
Bash
복사

Go 프로그램 구조

GO 모듈

go모듈은 프로젝트의 의존성을 관리하고, 소스 코드를 구성하는데 필요한 도구와 규약을 제공합니다.
기존의 GOPATH기반의 워크플로에서 벗어나 프로젝트별로 독립적인 의존성관리가 가능해집니다.
go.mod에 자신의 의존성을 선언하며, GO 도구체인은 이 파일을 사용하여 필요한 패키지를 자동으로 다운로드하고 버전을 관리합니다.
go.mod 파일에 선언된 의존성과 함께 go.sum 파일은 의존성의 특정 버전들을 체크섬으로 저장하여 의존성 그래프가 변경되지 않도록 합니다.
# 새로운 모듈 사용( go.mod 생성 ) go mod init [모듈명] # 자동 go.mod # 필요 패키지 추가 go.sum # 파일 업데이트 go get [패키지@버전] # 수동 업데이트 go list -m all # 모든 의존성과 버전 확인 go mod tidy # go.mod 정리(불필요한 의존성 제거)
Bash
복사

Go 패키지

Go에서 패키지는 코드를 구조화하고, 재사용하는 기본 단위입니다. 같은 패키지에 속한 파일들은 동일한 네임스페이스를 공유해서, 서로간의 함수, 변수, 타입등을 같은 파일에 있는 것처럼 접근이 가능합니다.
package main func Add(a, b int) int { return a + b }
Go
복사
add.go
package mathops // Subtract 는 첫 번째 정수에서 두 번째 정수를 뺀 결과를 반환합니다. func Subtract(a, b int) int { return a - b }
Go
복사
mathops/subtract.go
package main import ( "fmt" "calculate/mathops"" // 이 경로는 실제 패키지의 위치에 따라 달라집니다. ) func main() { result1 := mathops.Add(10, 5) result2 := mathops.Subtract(10, 5) fmt.Println("Addition Result:", result1) fmt.Println("Subtraction Result:", result2) }
Go
복사
main.go

Go 포인터

Go언어에서 포인터는 변수의 메모리 주소를 저장하며, 이를 통해 변수의 값을 직접적으로 변경할 수 있습니다.
*(역참조 연산자): 메모리 주소에 저장된 값을 접근합니다.
&(주소 연산지): 메모리의 주소를 반환합니다.
nil: pointer, channel, func, interface, map, or slice type의 기본값이다.
Golang의 경우 스택, 힙 메모리에 대해서 가비지 컬렉터가 알아서 정리를 하므로 크게 고민하지 않아도 된다.
package main import ( "fmt" ) func main() { var a int = 10 var b int = a var p *int = &a // a의 주소를 포인터 p에 할당 fmt.Println("a의 값:", a) // a의 값: 10 fmt.Println("a의 주소:", &a) // a의 주소: 0xc00000a0b8 fmt.Println("b의 값:", b) // b의 값: 10 fmt.Println("b의 주소:", &b) // b의 주소: 0xc00000a0d0 fmt.Println("p의 값:", p) // p의 값: 0xc00000a0b8 fmt.Println("*p의 값:", *p) // 포인터 p를 통해 a의 값을 간접적으로 출력 *p = 20 // 포인터 p를 통해 a의 값을 변경 fmt.Println("a의 새로운 값:", a) // a의 새로운 값: 20 fmt.Println("b의 새로운 값:", b) // b의 새로운 값: 10 }
Go
복사
함수를 사용할 때 포인터를 통해 변수를 넘기면, 변수의 값 변경을 할 수 있습니다.
package main import ( "fmt" ) // 포인터를 인자로 받아 그 포인터가 가리키는 값을 변경하는 함수 func increment(x *int) { *x = *x + 1 // 인자로 받은 포인터를 통해 값을 1 증가 } func main() { var n int = 10 fmt.Println("함수 호출 전 n의 값:", n) // 함수 호출 전 n의 값: 10 increment(&n) // n의 주소를 함수에 전달 fmt.Println("함수 호출 후 n의 값:", n) // 함수 호출 후 n의 값: 11 }
Go
복사

Go언어 연습 프로젝트

Go 계산기

package main import ( "calculate/mathops" "fmt" "os" ) func main() { var op string var num1, num2 float64 var err error fmt.Println("기호 입력(+, -, *, /)을 한뒤 2개의 숫자를 입력해주세요") _, err = fmt.Scanf("%s %f %f", &op, &num1, &num2) if err != nil { fmt.Println("Invalid input:", err) return } switch op { case "+": fmt.Println("Result:", Add(num1, num2)) case "-": fmt.Println("Result:", Subtract(num1, num2)) case "*": fmt.Println("Result:", mathops.Multiply(num1, num2)) case "/": if num2 == 0 { fmt.Println("Error: Division by zero") os.Exit(1) } fmt.Println("Result:", mathops.Divide(num1, num2)) default: fmt.Println("Unsupported operation:", op) } }
Go
복사
package main func Add(a, b float64) float64 { return a + b }
Go
복사
package main func Subtract(a, b float64) float64 { return a - b }
Go
복사
package mathops func Divide(a, b float64) float64 { return a / b }
Go
복사
package mathops func Multiply(a, b float64) float64 { return a * b }
Go
복사

GO 웹 서버

go는 net/http 패키지를 통해서 http 서버를 구축할 수 있습니다.
package main import ( "fmt" "net/http" ) func main() { // 웹 페이지 루트에서 "Welcome to my website!" 메시지를 표시 http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Welcome to my website!") }) // 정적 파일 처리 fs := http.FileServer(http.Dir("static/")) // /static/ 경로를 통해 정적 파일 제공 http.Handle("/static/", http.StripPrefix("/static/", fs)) // 포트 80에서 서버 시작 err := http.ListenAndServe(":18080", nil) if err != nil { // 서버 시작 시 오류 처리 fmt.Println("Error starting server:", err) } }
Go
복사
// Welcome to my website! http://localhost:18080/ // /static/apple.jpg 이미지 출력 http://localhost:18080/static/apple.jpg
Go
복사

커맨드 라인 툴

Go언어는 flag 라이브러리를 사용하여 커맨드 라인 인자를 처리하고, 복잡한 작업을 수행하는 스크립트 구현이 가능합니다.
package main import ( "flag" "fmt" ) func main() { // 사용자 이름 입력받기 name := flag.String("name", "Guest", "이름을 입력하세요. 기본값은 'Guest'입니다.") // 사용자 나이 입력받기 age := flag.Int("age", 0, "나이를 입력하세요. 기본값은 0입니다.") // 인사 메시지 활성화 여부 greet := flag.Bool("greet", false, "인사 메시지를 활성화하려면 '-greet=true'를 입력하세요.") // Flag 파싱 flag.Parse() // 조건에 따른 메시지 출력 if *greet { fmt.Printf("Hello, %s!\n", *name) if *age > 0 { fmt.Printf("Wow, you are %d years old!\n", *age) if *age < 18 { fmt.Println("You are considered a minor in most countries.") } else if *age < 65 { fmt.Println("Enjoy your years of adulthood.") } else { fmt.Println("Enjoy your retirement.") } } } else { fmt.Println("Greeting not enabled. Use '-greet=true' to see the greeting message.") } }
Go
복사
go build -o mycli.exe .\mycli.exe --greet --name "John Doe" --age 25 ./mycli -name="Jane Doe" .\mycli.exe --help
Go
복사

context 패키지

go 1.7부터 추가된 표준 패키지
context의 역할
중단, 마감을 알린다.
요청 또는 트랜잭션 범위의 메타데이터를 함수나 고루틴에 전달한다.
package main import "fmt" func main() { s := []int{2, 3, 5, 7, 11, 13} a := s[1:4] fmt.Println(a) b := s[:2] fmt.Println(b) c := s[1:] fmt.Println(c) d := s[:] fmt.Println(d) } [3 5 7] [2 3] [3 5 7 11 13] [2 3 5 7 11 13]
Go
복사

청크 예제

http.Flusher는 net/http의 인터페이스이며, HTTP 응답을 클라이언트로 청크 단위로 즉각 전송할 수 있도록 해줍니다.
type Flusher interface { Flush() }
Go
복사
package main import ( "archive/zip" "fmt" "io" "net/http" "time" ) func handlerChunkedZipResponse(w http.ResponseWriter, r *http.Request) { flusher, ok := w.(http.Flusher) if !ok { panic("expected http.ResponseWriter to be an http.Flusher") } // ZIP 파일 열기 zipReader, err := zip.OpenReader("/path/to/your/zip/file.zip") // 파일 경로 수정 if err != nil { http.Error(w, "Failed to open zip file", http.StatusInternalServerError) return } defer zipReader.Close() // ZIP 파일의 첫 번째 파일을 처리 (여러 파일 처리가 필요하다면 반복문 사용) file := zipReader.File[0] fileInZip, err := file.Open() if err != nil { http.Error(w, "Failed to read file inside zip", http.StatusInternalServerError) return } defer fileInZip.Close() // 파일을 청크로 나누어 전송 buffer := make([]byte, 4096) // 4KB 크기의 버퍼 for { n, err := fileInZip.Read(buffer) if err == io.EOF { break // 파일 끝에 도달 } if err != nil { http.Error(w, "Failed to read chunk from file", http.StatusInternalServerError) return } // 버퍼의 내용을 응답으로 작성 w.Write(buffer[:n]) flusher.Flush() // 클라이언트로 청크 전송 time.Sleep(500 * time.Millisecond) // 청크 사이의 지연 시간 (필요에 따라 조절) } } func main() { http.HandleFunc("/chunked-zip", handlerChunkedZipResponse) http.ListenAndServe(":18888", nil) }
Go
복사