변수

변수 선언

◾ 기본 방법

var a int
var a int = 10
var b,c,d int = 1,2,3  //동시에 여러개 변수 선언도 가능하다.

var키워드로 변수를 선언하고 변수명 다음 데이터 타입을 명시해주어야 하고, 선언만 하고 초기화를 해주지 않으면 go는 Zero value를 할당한다.

Zero Value
◾ 숫자 = 0
◾ bool = false
◾ string = “"


◾ 타입 추론

var a = 10
var q,w,e = 1, true, "#"   //동시에 여러개 변수 선언을 할때 다른 타입이더라도 추론을 통해 선언해준다.

위 처럼 변수 뒤의 타입형태를 제외한 형식의 타입추론도 가능하다.


◾ := (Short Assignment Statement)

package main
import "fmt"

func main(){
  a := 10
	fmt.Println(a)
}

변수선언하면서 초기화를 :=를 이용하면 var을 생략해서 작성이 가능하지만, 함수내에서만 가능하다.

package main
import "fmt"

a := 10     //error
var a = 10  //ok

func main(){
	fmt.Println(a);
}


◾ 여러개 지정

var (
  	a = 1
	b = 10
  	c = 20
)

중괄호 로 묶어 한번에 선언을 할 수도 있고 함수밖에 선언하면 같은 패키지에서 모두 사용할 수 있는 패키지 전역변수로 선언된다.



데이터 타입

◾ bool

true와 false만 갖는 bool형으로 기본 값은 false이고 c처럼 0이 false가 되지는 않는다.

◾ 문자열(string)

문자열을 나타내는 데이터 타입으로 Java와 같이 Immutable하기 때문에 한번 생성되면 수정 할 수 없다.

특정 변수의 문자열을 수정하는 것은 메모리내의 문자열을 수정하는 것이 아닌 다른 메모리에 수정한 문자열을 할당하고 그 메모리를 가르키도록 바꾼 것.

문자열 리터럴은 백틱(``), 이중인용부호("")를 이용해서 표현할 수 있다.

func main(){
	str := `ddd
ddd
ddd`
	fmt.Println(str)
}

//output
ddd
ddd
ddd
func main(){
	str := "ddd
  ddd
  ddd"  //error

  str := "ddd\nddd\nddd"  //success
	fmt.Println(str)
}

기본값은 빈 문자열 ("")이다.


◾ 정수(int)

뒤의 숫자는 메모리크기(bit)로 int32는 32bit(4byte)의 크기를 갖는 int타입인 것이다.

기본 값은 0이다.

1. 부호 있는 정수

int / int8 / int16/ int32/ int64

int는 컴퓨터의 환경에 따라 바뀌며 32bit컴퓨터는 int32, 64bit컴퓨터는 int64를 의미한다.

2. 부호 없는 양의 정수

uint / uint8 / uint15/ uint32 / uint64 / uintptr

uint는 int와 마찬가지로 컴퓨터의 환경에 따라 바뀌며 32bit컴퓨터는 uint32, 64bit컴퓨터는 uint64를 의미한다.


◾ 실수, 복소수

기본 값은 0.0이다.

1. 실수

float32 / float64

float64는 8byte를 갖으며 다른 언어의 double과 비슷하다

2. 복소수

complex64 : 진수와 가수 범위는 float32와 같다. complex128 : 진수와 가수 범위는 float64와 같다.


◾ byte

byte는 uint8의 aliasing(별칭)타입이다. uint8이 결국 1byte크기의 숫자 데이터이므로 byte와 같다.

int의 별칭형이기 때문에 기본값은 0이다.

◾ rune

문자 한개를 나타내는 타입으로 rune이 모여 string이 된다.

문자 1개는 UTF-8로 해당 인코딩 크기는 1~3byte의 가변 크기이므로 최소 3byte이상을 가져야 하는데 이진수를 활용하는 컴퓨터가 계산하기 편하게 4byte크기를 갖는 데이터 타입으로 int32의 aliasing이다.

func main(){
	a := '홍'
	fmt.Println(a)      //54861
  fmt.Printf("%c",a)  //홍

}

int의 별칭형이기 때문에 기본값은 0이다.


◾ 그 외 타입

기본 값은 nil로 nil은 정의되지 않은 메모리 주소를 나타내는 Go만의 키워드 이다.

1. type

type myInt int

c++의 typedef와 같이 type키워드를 이용해서 데이터타입에 대한 별칭을 정의 할 수 있다.

2. 배열

var a [4]int

b := [5]int{1,2,3,4,5}

var d [2][2]int

3. 슬라이스

배열의 일부로 동적 배열이라고 생각하면 된다.

a := make([]int, 3)
var b := []int{1,2,3}
var c []int = []int{}

배열과 생성방법은 비슷하나 배열길이를 처음에 명시하지 않으면 slice이며 길이가 0인상태로 생성된다.

내부에 길이를 뜻하는 len뿐만이 아닌 수용가능한 양을 표현하는 capacity도 있다.

4. 구조체

type Person struct{
	name string
}

type키워드를 이용해서 구조체를 정의할 수 있고, go는 class키워드가 존재하지 않고 필드의 집합인 struct과 메서드들도 클래스를 구현할 수 있다.

5. 포인터

메모리를 가르키는 포인터변수이며, C의 포인터와 비슷한 개념이다.

var a int = 1
b := &a
fmt.Println(b)
*b = 3
fmt.Println(*b)

6. Map

var a map[string]int = map[string]int
b := make(map[string]int)

7. 인터페이스

type Robot interface{
	getPrice() int
}

인터페이스는 메서드들의 집합으로 type 키워드를 이용해서 인터페이스를 정의할 수 있다.

8. 채널

스레드의 일종인 고루틴간의 데이터 통신을 위한 데이터 타입이다.

ch := make(chan int)
ch <- 123   //채널에 123을 전송
i = <- ch	//채널로부터 데이터를 받아옴



타입 변환

기본적인 방법으로 데이터타입() 함수를 이용해 데이터 타입을 변환 할 수 있다.

func main(){
	a := 10
	var b = 3.15
	var c = float64(a) * b
	fmt.Println(c)

	d := int64(a)
	e := int32(d)
	fmt.Println(string(d))
}

하지만 이는 bool이나 실수를 string등으로 형변환 할 수 없어 strconv모듈을 import하여 형변환을 수행할 수 도 있다.

◾ strconv

import (
	"fmt"
	"reflect"	//변수 type을 알아보기 위한 모듈
	"strconv"  	//형변환
)

func main() {
	fmt.Println("say hi")

	// Itoa : 정수를 문자열로 변환
	a := strconv.Itoa(100)
	fmt.Println("a: ", a)                      // a: 100
	fmt.Println("type a: ", reflect.TypeOf(a)) // type a: string

	// Atoi : 문자열을 정수로 변환
	b, _ := strconv.Atoi("100")
	fmt.Println("b: ", b)                      // b:  100
	fmt.Println("type b: ", reflect.TypeOf(b)) // type b: int

	// FormatInt : 특정값(100)을 특정 진수(10진수) 문자열로 변환
	aa := strconv.FormatInt(100, 10)
	fmt.Println("aa: ", aa)                      // aa: 100
	fmt.Println("type aa: ", reflect.TypeOf(aa)) // type aa: string

	// FormatBool : bool을 문자열로 변환
	c := strconv.FormatBool(true)
	fmt.Println("c: ", c)                      // c: true
	fmt.Println("type c: ", reflect.TypeOf(c)) // type c: string

	/*FormatFloat : 실수를 문자열로 변환
	  첫번째 인자 : 변경할 실수 값
	  두번째 인자 : 'f' : ddd.ddd와 같은 포맷 | 'e' : d.ddde+dd 포맷
	  세번째 인자 : 실수의 정밀도로 지수를 제외한 숫자의 자리수 ( -1입력시 자동으로 지정 )
	  네번째 인자 : 부동소수점 비트 수로 32,64 지정 */
	d := strconv.FormatFloat(1.3, 'f', -1, 32)
	fmt.Println("d: ", d)                      // d: 1.3
	fmt.Println("type d: ", reflect.TypeOf(d)) //type d: string

	//ParseInt : 문자열 100을 10진수 64bit크기의 정수형으로 변환
	bb, _ := strconv.ParseInt("100", 10, 64)
	fmt.Println("bb: ", bb)                      // bb: 100
	fmt.Println("type bb: ", reflect.TypeOf(bb)) // type bb: int64

	//ParseBool : bool형태의 문자열을 bool로 변환
	var b1 bool
	b1, err = strconv.ParseBool("true")
	fmt.Println(b1, err) // true <nil>

	//AppendBool : bool값을 문자열로 변환 후 slice뒤에 추가
	var s []byte = make([]byte, 0)
	s = strconv.AppendBool(s, true)
	fmt.Println(string(s)) // true

	//AppendFloat : 실수값을 문자열로 변환 후 slice뒤에 추가
	s = strconv.AppendFloat(s, 1.3, 'f', -1, 32)
	fmt.Println(string(s)) // true1.3

	//AppendInt : 정수값을 문자열로 변환 후 slice뒤에 추가
	s = strconv.AppendInt(s, -10, 10)
	fmt.Println(string(s)) // true1.3-10
}





Reference

『Tucker의 Go 언어 프로그래밍』 스터디 요약 노트

Tucker의 Go 강좌