Golang basic: Difference between revisions

From 탱이의 잡동사니
Jump to navigation Jump to search
(Created page with "== Overview == Golang basic 내용 정리 category:golang")
 
No edit summary
 
(4 intermediate revisions by the same user not shown)
Line 1: Line 1:
== Overview ==
== Overview ==
Golang basic 내용 정리
Golang basic 내용 정리
== select ==
The select statement is used to choose from multiple send/receive channel operations. The select statement blocks until one of the send/receive operation is ready.
If one or more of the communications can proceed, a single one that can proceed is chosen via a uniform pseudo-random selection. Otherwise, if there is a default case, that case is chosen. If there is no default case, the "select" statement blocks until at least one of the communications can proceed.
<source lang=go>
package main
import (
"context"
"fmt"
"time"
)
func main() {
fmt.Println("Clear is better than clever.")
ctx, canceled := context.WithCancel(context.Background())
canceled()
t := time.NewTicker(1 * time.Second)
out := make(chan int, 1)
select {
case <-ctx.Done():
fmt.Println("nope: canceled context selected")
case out <- work():
fmt.Println("work selected")
case <-t.C:
fmt.Println("ticker selected")
}
}
func work() int {
time.Sleep(10 * time.Second)
fmt.Printf("work work %#v\n", time.Now())
return 1
}
</source>
== Values ==
== Variables ==
var 키워드를 이용해서 선언한다. var 키워드 뒤에 변수명을 적고, 그 뒤에 변수타입을 적는다. 다음은 정수(int) 타입의 변수 a 를 선언한 것이다.
<source lang=go>
var a int
</source>
변수 선언문에서 변수 초기값을 할당할 수도 있다. 즉, float32 타입에 초기값을 입력하고자 한다면 다음과 같이 하면 된다.
<source lang=go>
var b float32 = 12.3
</source>
일단 선언된 변수는 해당 타입의 값을 할당할 수 있다.
<source lang=go>
a = 10
b = 1.23
</source>
만약 선언된 변수가 Go 프로그램에서 사용되지 않는다면, 에러를 발생시킨다. 따라서 사용되지 않는 변수는 프로그램에서 삭제해야 한다.
<pre>
$ go build ./main.go
# command-line-arguments
./main.go:22:7: k declared and not used
</pre>
동일한 타입의 변수가 여러 개 있을 경우, 변수들을 나열하고 마지막에 타입을 한번만 지정할 수 있다.
<source lang=go>
var i, j, k int = 1, 2, 3
</source>
변수를 선언하면서 초기값을 지정하지 않으면, Go 는 zero-value 를 기본적으로 할당한다. 숫자형에는 0, bool 타입에는 false, string 타입에는 ""(빈 문자열)을 할당한다.
Go 에서는 할당되는 값을 보고 그 타입을 추론하는 기능이 자주 사용된다.
아래의 예제에서는 i 에는 int, s 에는 string 타입이 자동으로 할당된다.
<source lang=go>
var i = 1
var s = "hi"
</source>
== Debug ==
=== GOTRACEBACK ===
환경변수에 GOTRACEBACK=crash 를 지정해놓으면, 문제 발생시 core dump 를 출력한다.
<pre>
$ ./main
panic: duplicate metrics collector registration attempted
goroutine 1 [running]:
panic(0x80b2a0, 0xc00000d040)
/usr/local/go/src/runtime/panic.go:556 +0x2cb fp=0xc0000dbe38 sp=0xc0000dbda8 pc=0x42c95b
github.com/prometheus/client_golang/prometheus.(*Registry).MustRegister(0xc0000a04b0, 0xc000083050, 0x1, 0x1)
/home/sungtaekim/go/src/github.com/prometheus/client_golang/prometheus/registry.go:391 +0xad fp=0xc0000dbe80 sp=0xc0000dbe38 pc=0x75cb9d
github.com/prometheus/client_golang/prometheus.MustRegister(0xc000083050, 0x1, 0x1)
/home/sungtaekim/go/src/github.com/prometheus/client_golang/prometheus/registry.go:176 +0x53 fp=0xc0000dbeb0 sp=0xc0000dbe80 pc=0x75b883
github.com/prometheus/client_golang/prometheus/promauto.NewCounter(0x0, 0x0, 0x0, 0x0, 0xc00008a270, 0x27, 0x861b42, 0x1f, 0x0, 0x8c80e0, ...)
/home/sungtaekim/go/src/github.com/prometheus/client_golang/prometheus/promauto/auto.go:136 +0xf2 fp=0xc0000dbf30 sp=0xc0000dbeb0 pc=0x7670c2
main.init()
/home/sungtaekim/worksapce/asterisk_exporter/main.go:106 +0xa55 fp=0xc0000dbf98 sp=0xc0000dbf30 pc=0x77cd35
runtime.main()
/usr/local/go/src/runtime/proc.go:189 +0x1bd fp=0xc0000dbfe0 sp=0xc0000dbf98 pc=0x42e63d
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1333 +0x1 fp=0xc0000dbfe8 sp=0xc0000dbfe0 pc=0x4591d1
goroutine 2 [force gc (idle)]:
runtime.gopark(0x872f90, 0xb98140, 0x1410, 0x1)
/usr/local/go/src/runtime/proc.go:302 +0xeb fp=0xc00003ef80 sp=0xc00003ef60 pc=0x42ea7b
runtime.goparkunlock(0xb98140, 0x1410, 0x1)
/usr/local/go/src/runtime/proc.go:308 +0x53 fp=0xc00003efb0 sp=0xc00003ef80 pc=0x42eb23
runtime.forcegchelper()
/usr/local/go/src/runtime/proc.go:251 +0xb3 fp=0xc00003efe0 sp=0xc00003efb0 pc=0x42e8f3
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1333 +0x1 fp=0xc00003efe8 sp=0xc00003efe0 pc=0x4591d1
created by runtime.init.4
/usr/local/go/src/runtime/proc.go:240 +0x35
goroutine 3 [GC sweep wait]:
runtime.gopark(0x872f90, 0xb983c0, 0x42140c, 0x1)
/usr/local/go/src/runtime/proc.go:302 +0xeb fp=0xc00003f780 sp=0xc00003f760 pc=0x42ea7b
runtime.goparkunlock(0xb983c0, 0x8b140c, 0x1)
/usr/local/go/src/runtime/proc.go:308 +0x53 fp=0xc00003f7b0 sp=0xc00003f780 pc=0x42eb23
runtime.bgsweep(0xc000066000)
/usr/local/go/src/runtime/mgcsweep.go:52 +0x8f fp=0xc00003f7d8 sp=0xc00003f7b0 pc=0x4213bf
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1333 +0x1 fp=0xc00003f7e0 sp=0xc00003f7d8 pc=0x4591d1
created by runtime.gcenable
/usr/local/go/src/runtime/mgc.go:216 +0x58
goroutine 18 [finalizer wait]:
runtime.gopark(0x872f90, 0xbb6048, 0x20000140f, 0x1)
/usr/local/go/src/runtime/proc.go:302 +0xeb fp=0xc00003e728 sp=0xc00003e708 pc=0x42ea7b
runtime.goparkunlock(0xbb6048, 0x40140f, 0x1)
/usr/local/go/src/runtime/proc.go:308 +0x53 fp=0xc00003e758 sp=0xc00003e728 pc=0x42eb23
runtime.runfinq()
/usr/local/go/src/runtime/mfinal.go:175 +0x99 fp=0xc00003e7e0 sp=0xc00003e758 pc=0x418d99
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1333 +0x1 fp=0xc00003e7e8 sp=0xc00003e7e0 pc=0x4591d1
created by runtime.createfing
/usr/local/go/src/runtime/mfinal.go:156 +0x61
Aborted (core dumped)
</pre>
== Marshal/Unmarshal ==
<source lang=go>
package main
import (
"encoding/json"
"fmt"
"log"
)
const input = `
{
"type": "sound",
"msg": {
"description": "dynamite",
"authority": "the Bruce Dickinson"
}
}
`
type Envelope struct {
Type string
Msg  interface{}
}
type Sound struct {
Description string
Authority  string
}
func main() {
var msg json.RawMessage
env := Envelope{
Msg: &msg,
}
if err := json.Unmarshal([]byte(input), &env); err != nil {
log.Fatal(err)
}
switch env.Type {
case "sound":
var s Sound
if err := json.Unmarshal(msg, &s); err != nil {
log.Fatal(err)
}
var desc string = s.Description
fmt.Println(desc)
default:
log.Fatalf("unknown message type: %q", env.Type)
}
}
</source>
* https://eagain.net/articles/go-dynamic-json/
== Errors ==
=== go get private repository return error ===
go build 를 하던 도중 다음과 같은 에러를 만났다. 원인은 필요 패키지 중 하나가 private repository 에 있었기 때문이었다.
<pre>
        gitlab.com/voipbin/bin-manager/common-handler.git/pkg/rabbitmqhandler: gitlab.com/voipbin/bin-manager/common-handler.git@v0.0.0-20210201031332-de387a37fc1c: verifying module: gitlab.com/voipbin/bin-manager/common-handler.git@v0.0.0-20210201031332-de387a37fc1c: reading https://sum.golang.org/lookup/gitlab.com/voipbin/bin-manager/common-handler.git@v0.0.0-20210201031332-de387a37fc1c: 410 Gone
</pre>
다음과 같은 환경변수를 추가 후, 정상작동을 확인했다.
<pre>
$ export GOPRIVATE="gitlab.com/voipbin"
</pre>
== Reference ==
* http://golang.site - 예제로 배우는 Go 프로그래밍


[[category:golang]]
[[category:golang]]

Latest revision as of 04:22, 1 February 2021

Overview

Golang basic 내용 정리

select

The select statement is used to choose from multiple send/receive channel operations. The select statement blocks until one of the send/receive operation is ready.

If one or more of the communications can proceed, a single one that can proceed is chosen via a uniform pseudo-random selection. Otherwise, if there is a default case, that case is chosen. If there is no default case, the "select" statement blocks until at least one of the communications can proceed. <source lang=go> package main

import ( "context" "fmt" "time" )

func main() { fmt.Println("Clear is better than clever.") ctx, canceled := context.WithCancel(context.Background()) canceled()

t := time.NewTicker(1 * time.Second)

out := make(chan int, 1) select { case <-ctx.Done(): fmt.Println("nope: canceled context selected") case out <- work(): fmt.Println("work selected") case <-t.C: fmt.Println("ticker selected") } }

func work() int { time.Sleep(10 * time.Second) fmt.Printf("work work %#v\n", time.Now()) return 1 } </source>

Values

Variables

var 키워드를 이용해서 선언한다. var 키워드 뒤에 변수명을 적고, 그 뒤에 변수타입을 적는다. 다음은 정수(int) 타입의 변수 a 를 선언한 것이다. <source lang=go> var a int </source>

변수 선언문에서 변수 초기값을 할당할 수도 있다. 즉, float32 타입에 초기값을 입력하고자 한다면 다음과 같이 하면 된다. <source lang=go> var b float32 = 12.3 </source>

일단 선언된 변수는 해당 타입의 값을 할당할 수 있다. <source lang=go> a = 10 b = 1.23 </source>

만약 선언된 변수가 Go 프로그램에서 사용되지 않는다면, 에러를 발생시킨다. 따라서 사용되지 않는 변수는 프로그램에서 삭제해야 한다.

$ go build ./main.go 
# command-line-arguments
./main.go:22:7: k declared and not used

동일한 타입의 변수가 여러 개 있을 경우, 변수들을 나열하고 마지막에 타입을 한번만 지정할 수 있다. <source lang=go> var i, j, k int = 1, 2, 3 </source>

변수를 선언하면서 초기값을 지정하지 않으면, Go 는 zero-value 를 기본적으로 할당한다. 숫자형에는 0, bool 타입에는 false, string 타입에는 ""(빈 문자열)을 할당한다.

Go 에서는 할당되는 값을 보고 그 타입을 추론하는 기능이 자주 사용된다.

아래의 예제에서는 i 에는 int, s 에는 string 타입이 자동으로 할당된다. <source lang=go> var i = 1 var s = "hi" </source>

Debug

GOTRACEBACK

환경변수에 GOTRACEBACK=crash 를 지정해놓으면, 문제 발생시 core dump 를 출력한다.

$ ./main
panic: duplicate metrics collector registration attempted

goroutine 1 [running]:
panic(0x80b2a0, 0xc00000d040)
	/usr/local/go/src/runtime/panic.go:556 +0x2cb fp=0xc0000dbe38 sp=0xc0000dbda8 pc=0x42c95b
github.com/prometheus/client_golang/prometheus.(*Registry).MustRegister(0xc0000a04b0, 0xc000083050, 0x1, 0x1)
	/home/sungtaekim/go/src/github.com/prometheus/client_golang/prometheus/registry.go:391 +0xad fp=0xc0000dbe80 sp=0xc0000dbe38 pc=0x75cb9d
github.com/prometheus/client_golang/prometheus.MustRegister(0xc000083050, 0x1, 0x1)
	/home/sungtaekim/go/src/github.com/prometheus/client_golang/prometheus/registry.go:176 +0x53 fp=0xc0000dbeb0 sp=0xc0000dbe80 pc=0x75b883
github.com/prometheus/client_golang/prometheus/promauto.NewCounter(0x0, 0x0, 0x0, 0x0, 0xc00008a270, 0x27, 0x861b42, 0x1f, 0x0, 0x8c80e0, ...)
	/home/sungtaekim/go/src/github.com/prometheus/client_golang/prometheus/promauto/auto.go:136 +0xf2 fp=0xc0000dbf30 sp=0xc0000dbeb0 pc=0x7670c2
main.init()
	/home/sungtaekim/worksapce/asterisk_exporter/main.go:106 +0xa55 fp=0xc0000dbf98 sp=0xc0000dbf30 pc=0x77cd35
runtime.main()
	/usr/local/go/src/runtime/proc.go:189 +0x1bd fp=0xc0000dbfe0 sp=0xc0000dbf98 pc=0x42e63d
runtime.goexit()
	/usr/local/go/src/runtime/asm_amd64.s:1333 +0x1 fp=0xc0000dbfe8 sp=0xc0000dbfe0 pc=0x4591d1

goroutine 2 [force gc (idle)]:
runtime.gopark(0x872f90, 0xb98140, 0x1410, 0x1)
	/usr/local/go/src/runtime/proc.go:302 +0xeb fp=0xc00003ef80 sp=0xc00003ef60 pc=0x42ea7b
runtime.goparkunlock(0xb98140, 0x1410, 0x1)
	/usr/local/go/src/runtime/proc.go:308 +0x53 fp=0xc00003efb0 sp=0xc00003ef80 pc=0x42eb23
runtime.forcegchelper()
	/usr/local/go/src/runtime/proc.go:251 +0xb3 fp=0xc00003efe0 sp=0xc00003efb0 pc=0x42e8f3
runtime.goexit()
	/usr/local/go/src/runtime/asm_amd64.s:1333 +0x1 fp=0xc00003efe8 sp=0xc00003efe0 pc=0x4591d1
created by runtime.init.4
	/usr/local/go/src/runtime/proc.go:240 +0x35

goroutine 3 [GC sweep wait]:
runtime.gopark(0x872f90, 0xb983c0, 0x42140c, 0x1)
	/usr/local/go/src/runtime/proc.go:302 +0xeb fp=0xc00003f780 sp=0xc00003f760 pc=0x42ea7b
runtime.goparkunlock(0xb983c0, 0x8b140c, 0x1)
	/usr/local/go/src/runtime/proc.go:308 +0x53 fp=0xc00003f7b0 sp=0xc00003f780 pc=0x42eb23
runtime.bgsweep(0xc000066000)
	/usr/local/go/src/runtime/mgcsweep.go:52 +0x8f fp=0xc00003f7d8 sp=0xc00003f7b0 pc=0x4213bf
runtime.goexit()
	/usr/local/go/src/runtime/asm_amd64.s:1333 +0x1 fp=0xc00003f7e0 sp=0xc00003f7d8 pc=0x4591d1
created by runtime.gcenable
	/usr/local/go/src/runtime/mgc.go:216 +0x58

goroutine 18 [finalizer wait]:
runtime.gopark(0x872f90, 0xbb6048, 0x20000140f, 0x1)
	/usr/local/go/src/runtime/proc.go:302 +0xeb fp=0xc00003e728 sp=0xc00003e708 pc=0x42ea7b
runtime.goparkunlock(0xbb6048, 0x40140f, 0x1)
	/usr/local/go/src/runtime/proc.go:308 +0x53 fp=0xc00003e758 sp=0xc00003e728 pc=0x42eb23
runtime.runfinq()
	/usr/local/go/src/runtime/mfinal.go:175 +0x99 fp=0xc00003e7e0 sp=0xc00003e758 pc=0x418d99
runtime.goexit()
	/usr/local/go/src/runtime/asm_amd64.s:1333 +0x1 fp=0xc00003e7e8 sp=0xc00003e7e0 pc=0x4591d1
created by runtime.createfing
	/usr/local/go/src/runtime/mfinal.go:156 +0x61
Aborted (core dumped)

Marshal/Unmarshal

<source lang=go> package main

import ( "encoding/json" "fmt" "log" )

const input = ` { "type": "sound", "msg": { "description": "dynamite", "authority": "the Bruce Dickinson" } } `

type Envelope struct { Type string Msg interface{} }

type Sound struct { Description string Authority string }

func main() { var msg json.RawMessage env := Envelope{ Msg: &msg, } if err := json.Unmarshal([]byte(input), &env); err != nil { log.Fatal(err) } switch env.Type { case "sound": var s Sound if err := json.Unmarshal(msg, &s); err != nil { log.Fatal(err) } var desc string = s.Description fmt.Println(desc) default: log.Fatalf("unknown message type: %q", env.Type) } } </source>

Errors

go get private repository return error

go build 를 하던 도중 다음과 같은 에러를 만났다. 원인은 필요 패키지 중 하나가 private repository 에 있었기 때문이었다.

        gitlab.com/voipbin/bin-manager/common-handler.git/pkg/rabbitmqhandler: gitlab.com/voipbin/bin-manager/common-handler.git@v0.0.0-20210201031332-de387a37fc1c: verifying module: gitlab.com/voipbin/bin-manager/common-handler.git@v0.0.0-20210201031332-de387a37fc1c: reading https://sum.golang.org/lookup/gitlab.com/voipbin/bin-manager/common-handler.git@v0.0.0-20210201031332-de387a37fc1c: 410 Gone

다음과 같은 환경변수를 추가 후, 정상작동을 확인했다.

$ export GOPRIVATE="gitlab.com/voipbin"

Reference