A Tour of Go 1

태그: ,

카테고리: ,

출처 Go Tour

🚫 아래 내용은 주관적인 생각이므로 사실과 다를 수 있습니다.



Packages

package main

import (
	"fmt"
	"math/rand"
)

func main() {
	fmt.Println("My favorite number is", rand.Intn(10))
}

모든 Go 프로그램은 패키지들로 만들어진다
Go 컴파일러가 위 코드 맨 윗줄의 package main를 보고 실행 프로그램으로 인식한다


Imports

import "fmt"
import "math"

패키지를 임포트 할 때, 위와 같이 하나하나 임포트해도 되지만
아래와 같이 그룹지어 임포트 하는 방식(factored import문)을 권장한다

import (
	"fmt"
	"math/rand"
)

Exported names

package main

import (
	"fmt"
	"math"
)

func main() {
	fmt.Println(math.pi)
}
// ./prog.go:9:14: cannot refer to unexported name math.pi
// math.pi를 math.Pi로 바꾸면 3.141592653589793

Go에서는 대문자로 시작하는 이름이 Export되는 이름이다
위 코드 중 main() 안의 fmt.Println(math.pi) 구문은
math에서 대문자로 시작하지 않는 pi를 사용하려하고
이는 에러를 발생시킨다


Functions 1

package main

import "fmt"

func add(x int, y int) int {
	return x + y
}

func main() {
	fmt.Println(add(42, 13))
}
// 55

함수는 0개 또는 그 이상의 파라미터를 가질 수 있다
위의 코드에서 add 함수는 두 개의 파라미터를 받는데,
변수명 뒤에 타입을 기재하는것을 확인할 수 있다
왜 그러는지는 여기에서 확인할 수 있다


Functions 2

package main

import "fmt"

func add(x, y int) int {
	return x + y
}

func main() {
	fmt.Println(add(42, 13))
}
// 55

같은 타입의 파라미터를 여러개 받는다면,
타입을 전부 생략하고 마지막에만 붙여줘도 된다


Multiple results

package main

import "fmt"

func swap(x, y string) (string, string) {
	return y, x
}

func main() {
	a, b := swap("hello", "world")
	fmt.Println(a, b)
}
// world hello

함수는 다수의 반환값을 가질수 있다
위 코드의 swap 함수는 2개의 string들을 반환한다


Named return values

package main

import "fmt"

func split(sum int) (x, y int) {
	x = sum * 4 / 9
	y = sum - x
	return
}

func main() {
	fmt.Println(split(17))
}
// 7 10

위 코드의 split 함수처럼 반환값에도 이름을 정하고, 함수 내에서 사용할 수 있다
또한, 위와 같은 반환 인자가 없는 return문을 naked return문이라고 한다
긴 함수에서는 가독성을 떨어뜨릴수 있기 때문에 짧은 함수에서만 사용하길 권장한다


Variables

package main

import "fmt"

var c, python, java bool

func main() {
	var i int
	fmt.Println(i, c, python, java)
}
// 0 false false false

위처럼 var문으로 변수 목록을 선언하고
이전 예시들처럼 마지막에 타입을 기재해준다
var문은 패키지나 함수 레벨에서 쓰일 수 있다


Variables with initializers

package main

import "fmt"

var i, j int = 1, 2

func main() {
	var c, python, java = true, false, "no!"
	fmt.Println(i, j, c, python, java)
}
// 1 2 true false no!

변수를 선언할 때, 변수 하나당 하나의 초기값을 할당할 수 있다
초기값을 할당하고 타입을 생략하면, 변수의 타입은 초기값의 타입으로 정해진다


Short variable declarations

package main

import "fmt"

func main() {
	var i, j int = 1, 2
	k := 3
	c, python, java := true, false, "no!"

	fmt.Println(i, j, k, c, python, java)
}
// 1 2 3 true false no!

함수 안에 보이는 := 기호로 짧은 변수 선언이 가능하다
짧은 변수 선언은 var 선언처럼 사용될 수 있으며
타입 또한 암시적으로 할당된다

그러나 함수 밖에서는 모든 구문들이 다른 키워드들로 시작하므로
짧은 변수 선언은 사용할 수 없다


Basic types

Go의 기본적인 타입들은 아래와 같다

bool

string

int  int8  int16  int32  int64
uint uint8 uint16 uint32 uint64 uintptr

byte // uint8와 같다

rune // int32와 같다
     // Unicode 중 code point를 나타낸다

float32 float64

complex64 complex128

아래의 예시에서 몇 가지 타입의 변수들과
import문처럼 블록 안에서 factored 형태로 선언되는 방식을 확인할 수 있다

int, uint, uintptr 타입들은 보통
시스템에 따라 32-bit 시스템에서는 32 bit,
64-bit 시스템에서는 64 bit의 길이를 가진다
정수 값을 쓸 때는 특별한 상황이 아니라면 int를 사용하자

package main

import (
	"fmt"
	"math/cmplx"
)

var (
	ToBe   bool       = false
	MaxInt uint64     = 1<<64 - 1
	z      complex128 = cmplx.Sqrt(-5 + 12i)
)

func main() {
	fmt.Printf("Type: %T Value: %v\n", ToBe, ToBe)
	fmt.Printf("Type: %T Value: %v\n", MaxInt, MaxInt)
	fmt.Printf("Type: %T Value: %v\n", z, z)
}
// Type: bool Value: false
// Type: uint64 Value: 18446744073709551615
// Type: complex128 Value: (2+3i)

Zero values

package main

import "fmt"

func main() {
	var i int
	var f float64
	var b bool
	var s string
	fmt.Printf("%v %v %v %q\n", i, f, b, s)
}
// 0 0 false ""

명시적인 초기값 없이 선언된 변수들은 각 타입에 맞는 zero vlaue를 갖는다

  • 숫자들은 0
  • 불리언은 false
  • String은 “”

Type conversions

package main

import (
	"fmt"
	"math"
)

func main() {
	var x, y int = 3, 4
	var f float64 = math.Sqrt(float64(x*x + y*y))
	var z uint = uint(f)
	fmt.Println(x, y, z)
}
// 3 4 5

표현식 T(v) 에서 값 v는 T 타입으로 변환된다

몇가지 숫자 형변환 예시

var i int = 42
var f float64 = float64(i)
var u uint = uint(f)

아니면 아래와 같이 더 간단하게 할 수도 있다

i := 42
f := float64(i)
u := uint(f)

C랑은 다르게 Go에서는 명시적인 형변환이 필요하다


Type inference

package main

import "fmt"

func main() {
	v := 42 // change me!
	fmt.Printf("v is of type %T\n", v)
}
// v is of type int

명시적으로 타입을 지정 안해주면 우측의 값을 보고 추론한다
우측의 값의 타입이 이미 정해져있다면, 그 타입을 그대로 따른다

var i int
j := i // i가 int니까 j도 int다

그러나 우측의 값이 지정되지 않은 타입의 숫자인 경우에는
그 정밀도를 보고 추론한다

i := 42           // int
f := 3.142        // float64
g := 0.867 + 0.5i // complex128

Constants

package main

import "fmt"

const Pi = 3.14

func main() {
	const World = "世界"
	fmt.Println("Hello", World)
	fmt.Println("Happy", Pi, "Day")

	const Truth = true
	fmt.Println("Go rules?", Truth)
}
// Hello 世界
// Happy 3.14 Day
// Go rules? true

상수는 변수처럼 선언되지만 var 키워드 대신 const 키워드를 사용한다
상수는 character, string, boolean, numeric값이 될 수 있으며
:= 기호(짧은 변수 선언)로는 선언이 불가하다


Numeric Constants

package main

import "fmt"

const (
	// 1 비트를 왼쪽으로 100번 시프트해서 큰 숫자를 만들어보자
	// 1 뒤에 0이 100개 붙은 이진수가 된다
	Big = 1 << 100
	// 다시 오른쪽으로 99번 시프트 해보자. 1<<1, 즉, 2가 된다
	Small = Big >> 99
)

func needInt(x int) int {
    return x * 10 + 1
}

func needFloat(x float64) float64 {
	return x * 0.1
}

func main() {
	fmt.Println(needInt(Small))
	fmt.Println(needFloat(Small))
	fmt.Println(needFloat(Big))
}
// 21
// 0.2
// 1.2676506002282295e+29

// fmt.Println(needInt(Big))으로 바꾸면 아래와 같은 에러가 발생한다  
// ./prog.go:19:21: constant 1267650600228229401496703205376 overflows int

변수에 값을 할당할 때, 변수가 값을 담기에 충분한지 확인하자

댓글남기기