var k int = 10
var p = &k //k의 주소를 할당
println(*p) //p가 가리키는 주소에 있는 실제 내용을 출력
names := []string{"홍길동", "이순신", "강감찬"}
for index, name := range names {
println(index, name)
}
package main
func main() {
i := 0
L1:
for {
if i == 0 {
break L1
}
}
println("OK")
}
package main
func main() {
say("This", "is", "a", "book")
say("Hi")
}
func say(msg ...string) {
for _, s := range msg {
println(s)
}
}
package main
func main() {
count, total := sum(1, 7, 3, 5, 9)
println(count, total)
}
//리턴값 복수
func sum(nums ...int) (int, int) {
s := 0 // 합계
count := 0 // 요소 갯수
for _, n := range nums {
s += n
count++
}
return count, s
}
// Named Return Parameter = count int, total int
func sum(nums ...int) (count int, total int) {
for _, n := range nums {
total += n
}
count = len(nums)
return
}
package main
func main() {
//변수 add 에 익명함수 할당
add := func(i int, j int) int {
return i + j
}
// add 함수 전달
r1 := calc(add, 10, 20)
println(r1)
// 직접 첫번째 파라미터에 익명함수를 정의함
r2 := calc(func(x int, y int) int { return x - y }, 10, 20)
println(r2)
}
func calc(f func(int, int) int, a int, b int) int {
result := f(a, b)
return result
}
// 원형 정의
type calculator func(int, int) int
// calculator 원형 사용
func calc(f calculator, a int, b int) int {
result := f(a, b)
return result
}
package main
func nextValue() func() int {
i := 0
return func() int {
i++
return i
}
}
func main() {
next := nextValue()
println(next()) // 1
println(next()) // 2
println(next()) // 3
anotherNext := nextValue()
println(anotherNext()) // 1 다시 시작
println(anotherNext()) // 2
}
func main() {
s := make([]int, 5, 10)
println(len(s), cap(s)) // len 5, cap 10
}
// 슬라이스에 별도의 길이와 용량을 지정하지 않으면,
기본적으로 길이와 용량이 0 인 슬라이스를 만드는데,
이를 Nil Slice 라 하고, nil 과 비교하면 참을 리턴한다.
func main() {
var s []int
if s == nil {
println("Nil Slice")
}
println(len(s), cap(s)) // 모두 0
}
s := []int{0, 1, 2, 3, 4, 5}
s = s[2:5] // 2, 3, 4
s = s[1:] // 3, 4
fmt.Println(s) // 3, 4 출력
package main
import "fmt"
func main() {
// len=0, cap=3 인 슬라이스
sliceA := make([]int, 0, 3)
// 계속 한 요소씩 추가
for i := 1; i <= 15; i++ {
sliceA = append(sliceA, i)
// 슬라이스 길이와 용량 확인
fmt.Println(len(sliceA), cap(sliceA))
}
fmt.Println(sliceA) // 1 부터 15 까지 숫자 출력
}
func main() {
source := []int{0, 1, 2}
target := make([]int, len(source), cap(source)*2)
copy(target, source)
fmt.Println(target) // [0 1 2 ] 출력
println(len(target), cap(target)) // 3, 6 출력
}
tickers := map[string]string{
"GOOG": "Google Inc",
"MSFT": "Microsoft",
"FB": "FaceBook",
}
package main
func main() {
tickers := map[string]string{
"GOOG": "Google Inc",
"MSFT": "Microsoft",
"FB": "FaceBook",
"AMZN": "Amazon",
}
// map 키 체크
val, exists := tickers["MSFT"]
if !exists {
println("No MSFT ticker")
}
for key, val := range tickers {
fmt.Println(key, val)
}
}
package testlib
var pop map[string]string
func init() { // 패키지 로드시 map 초기화
pop = make(map[string]string)
}
package main
import _ "other/xlib" //그 패키지 안의 init() 함수만을 호출하고자 하는 케이스
// 패키지 alias를 사용해서 구분
import (
mongo "other/mongo/db"
mysql "other/mysql/db"
)
func main() {
mondb := mongo.Get()
mydb := mysql.Get()
//...
}
package main
import "fmt"
// struct 정의
type person struct {
name string
age int
}
func main() {
// person 객체 생성
p := person{}
// 필드값 설정
p.name = "Lee"
p.age = 10
fmt.Println(p)
}
package main
//Rect - struct 정의
type Rect struct {
width, height int
}
//Rect의 area() 메소드
func (r Rect) area() int {
return r.width * r.height
}
func main() {
rect := Rect{10, 20}
area := rect.area() //메서드 호출
println(area)
}
type Shape interface {
area() float64
perimeter() float64
}
//Rect 정의
type Rect struct {
width, height float64
}
//Circle 정의
type Circle struct {
radius float64
}
//Rect 타입에 대한 Shape 인터페이스 구현
func (r Rect) area() float64 { return r.width * r.height }
func (r Rect) perimeter() float64 {
return 2 * (r.width + r.height)
}
//Circle 타입에 대한 Shape 인터페이스 구현
func (c Circle) area() float64 {
return math.Pi * c.radius * c.radius
}
func (c Circle) perimeter() float64 {
return 2 * math.Pi * c.radius
}
func Marshal(v interface{}) ([]byte, error);
func Println(a ...interface{}) (n int, err error);
// 인터페이스는 어떠한 타입도 담을 수 있는 컨테이너라고 볼 수 있으며,
여러 다른 언어에서 흔히 일컫는 Dynamic Type 이라고 볼 수 있다.
(주: empty interface는 C#, Java 에서 object라 볼 수 있으며,
C/C++ 에서는 void* 와 같다고 볼 수 있다)
// Interface type의 x와 타입 T에 대하여 x.(T)로 표현했을 때,
이는 x가 nil이 아니며, x는 T 타입에 속한다는 점을 확인(assert)하는 것으로
이러한 표현을 "Type Assertion"이라 부른다.
func main() {
var a interface{} = 1
i := a // a와 i 는 dynamic type, 값은 1
j := a.(int) // j는 int 타입, 값은 1
println(i) // 포인터주소 출력
println(j) // 1 출력
}
type error interface {
Error() string
}
package main
import (
"log"
"os"
)
func main() {
f, err := os.Open("C:\\temp\\1.txt")
if err != nil {
log.Fatal(err.Error())
}
println(f.Name())
}
_, err := otherFunc()
switch err.(type) {
default: // no error
println("ok")
case MyError:
log.Print("Log my error")
case error:
log.Fatal(err.Error())
}
package main
import "os"
func main() {
f, err := os.Open("1.txt")
if err != nil {
panic(err)
}
// main 마지막에 파일 close 실행
defer f.Close()
// 파일 읽기
bytes := make([]byte, 1024)
f.Read(bytes)
println(len(bytes))
}
package main
import "os"
func main() {
openFile("Invalid.txt")
println("Done") //이 문장은 실행 안됨
}
func openFile(fn string) {
f, err := os.Open(fn)
if err != nil {
panic(err)
}
// 파일 close 실행됨
defer f.Close()
}
package main
import (
"fmt"
"os"
)
func main() {
openFile("1.txt")
println("Done") // 이 문장 실행됨
}
func openFile(fn string) {
// defere 함수. panic 호출시 실행됨
defer func() {
if r := recover(); r != nil {
fmt.Println("OPEN ERROR", r)
}
}()
f, err := os.Open(fn)
if err != nil {
panic(err)
}
// 파일 close 실행됨
defer f.Close()
}
// goroutine은 OS 쓰레드보다 훨씬 가볍게 비동기 Concurrent 처리를
구현하기 위하여 만든 것으로, 기본적으로 Go 런타임이 자체 관리한다.
Go 런타임 상에서 관리되는 작업단위인 여러 goroutine들은
종종 하나의 OS 쓰레드 1개로도 실행되곤 한다.
즉, Go루틴들은 OS 쓰레드와 1 대 1로 대응되지 않고,
Multiplexing으로 훨씬 적은 OS 쓰레드를 사용한다.
메모리 측면에서도 OS 쓰레드가 1 메가바이트의 스택을 갖는 반면,
goroutine은 이보다 훨씬 작은 몇 킬로바이트의 스택을 갖는다(필요시 동적으로 증가).
Go 런타임은 Go루틴을 관리하면서 Go 채널을 통해 Go루틴 간의 통신을 쉽게 할 수 있도록 하였다.
package main
import (
"fmt"
"time"
)
func say(s string) {
for i := 0; i < 10; i++ {
fmt.Println(s, "***", i)
}
}
func main() {
// 함수를 동기적으로 실행
say("Sync")
// 함수를 비동기적으로 실행
go say("Async1")
go say("Async2")
go say("Async3")
// 3초 대기
time.Sleep(time.Second * 3)
}
package main
import (
"fmt"
"sync"
)
func main() {
// WaitGroup 생성. 2개의 Go루틴을 기다림.
// sync.WaitGroup을 사용하고 있는데,
이는 기본적으로 여러 Go루틴들이 끝날 때까지 기다리는 역활
var wait sync.WaitGroup
wait.Add(2)
// 익명함수를 사용한 goroutine
go func() {
defer wait.Done() //끝나면 .Done() 호출
fmt.Println("Hello")
}()
// 익명함수에 파라미터 전달
go func(msg string) {
defer wait.Done() //끝나면 .Done() 호출
fmt.Println(msg)
}("Hi")
wait.Wait() //Go루틴 모두 끝날 때까지 대기
}
package main
import (
"runtime"
)
func main() {
// 4개의 CPU 사용
runtime.GOMAXPROCS(4)
//...
}
package main
func main() {
// 정수형 채널을 생성한다
ch := make(chan int)
go func() {
ch <- 123 //채널에 123을 보낸다
}()
var i int
i = <- ch // 채널로부터 123을 받는다
println(i)
}
package main
import "fmt"
func main() {
done := make(chan bool)
go func() {
for i := 0; i < 10; i++ {
fmt.Println(i)
}
done <- true
}()
// 위의 Go루틴이 끝날 때까지 대기
<-done
}
package main
import "fmt"
func main() {
c := make(chan int)
c <- 1 //수신루틴이 없으므로 데드락
fmt.Println(<-c) //코멘트해도 데드락 (별도의 Go루틴없기 때문)
}
package main
import "fmt"
func main() {
ch := make(chan int, 1)
//수신자가 없더라도 보낼 수 있다.
ch <- 101
fmt.Println(<-ch)
}
package main
import "fmt"
func main() {
ch := make(chan string, 1)
sendChan(ch)
receiveChan(ch)
}
func sendChan(ch chan<- string) {
ch <- "Data"
// x := <-ch // 에러발생
}
func receiveChan(ch <-chan string) {
data := <-ch
fmt.Println(data)
}
package main
func main() {
ch := make(chan int, 2)
// 채널에 송신
ch <- 1
ch <- 2
// 채널을 닫는다
close(ch)
// 채널 수신
println(<-ch)
println(<-ch)
if _, success := <-ch; !success {
println("더이상 데이타 없음.")
}
}
package main
func main() {
ch := make(chan int, 2)
// 채널에 송신
ch <- 1
ch <- 2
// 채널을 닫는다
close(ch)
// 방법1
// 채널이 닫힌 것을 감지할 때까지 계속 수신
/*
for {
if i, success := <-ch; success {
println(i)
} else {
break
}
}
*/
// 방법2
// 위 표현과 동일한 채널 range 문
for i := range ch {
println(i)
}
}
첫번째 run1()이 1초간 실행되고 done1 채널로부터 수신하여 해당 case를 실행하고,
다시 for 루프를 돈다.
for루프를 다시 돌면서 다시 select문이 실행되는데,
다음 run2()가 2초후에 실행되고 done2 채널로부터 수신하여 해당 case를 실행하게 된다.
done2 채널 case문에 break EXIT 이 있는데,
이 문장으로 인해 for 루프를 빠져나와 EXIT 레이블로 이동하게 된다
package main
import "time"
func main() {
done1 := make(chan bool)
done2 := make(chan bool)
go run1(done1)
go run2(done2)
EXIT:
for {
select {
case <-done1:
println("run1 완료")
case <-done2:
println("run2 완료")
break EXIT
}
}
}
func run1(done chan bool) {
time.Sleep(1 * time.Second)
done <- true
}
func run2(done chan bool) {
time.Sleep(2 * time.Second)
done <- true
}