Go를 배워보자 1일차 - GO의 기본 구조와 변수, 타입
Go? GO!
1. Go는 무엇이며? 왜 배워야할까??
필자는 4G/5G 통신 서버 개발자라 속도에 민감해 c/c++만을 사용한다. 그런데 요즘들어 여러 통신 서버 개발자 분들이 golang을 사용하는 것을 보았고 좋아보여서 공부해보려고 한다.
사실 필자도 잘모르겠다. 그냥 로고가 귀여워서 공부하려고한다.힙찔이
2. 어떻게 다운받으면 될까?
여기에 들어가서 자신의 플랫폼에 맞는 다운로드 파일을 설치하면 된다.
금방 설치되서 아주 좋다.
3. hello world 출력해보기
개발자들 대부분이 하는 말 중에 그 언어의 "hello world"까지 해보았다면 절반은 아는 것이다. 라는 띵언이 있다.
물론 이 말에 죽자고 달려드는 -찐- 들도 있지만, '시작이 반이다' 라는 속담처럼 개발자들 사이의 속담으로 생각하면 된다.
먼저 main.go 파일을 만들어보도록 하자
main.go
package main
import "fmt"
func main() {
fmt.Println("Hello World")
}
그럼 실행을 해보자 터미널에서 다음의 명령어를 입력하면 된다.
go run main.go
다음의 결과가 나올 것이다.
Hello World
Go의 기본 코드를 분석하면 코드 구조를 쉽게 알 수 있다.
- package : 현재 파일이 어떤 패키지에 속하는 지를 알려준다.
- import : 어떤 코드에서 다른 패키지에 있는 코드를 사용하기 위해 패키지를 가져오는 것이다.
- func main() {} : c/c++, java의 main함수와 같은 entry point 역할을 한다. API 함수의 경우는 굳이 main을 만들 필요는 없지만, 구동이 필요하다면 main이 있어야 한다.
- fmt.Println() : fmt는 format이라는 의미로 "fmt" 패키지에 있다. 이를 통해 서식 문자로 출력이 가능하다.
결국 정리하자면 Go 파일은 3가지 부분으로 나눌 수 있다.
1. package 절
2. import 문
3. 코드
참고로 golang은 js처럼 세미콜론(;)을 써도되고 안써도된다. 물론 써주는게 가독성 측면에서 좋다.
재미있는 것은 golang은 실제 참조하는 package만 가져오려고 한다는 것이다. 만약 vscode에서 extension을 깔아놓고 쓸 떼 fmt.Println() 함수를 지워보자, 그러면 자동으로 import의 "fmt"로 사라진다.
이는 "fmt"가 안쓰였기 때문이다.
4. import문으로 다른 패키지의 함수 사용하기
굉장히 단순하다
package main
import (
"math"
"strings"
)
func main() {
math.Floor(2.75)
strings.Title("hello")
}
가져오려는 package들을 import() 안에 콤마(,)없이 "" 로 하나씩 써주면 된다.
여기서 조심해야할 것은 go는 c/c++처럼 ''와 ""을 구분하므로 잘 알아두자
5. Go의 타입들
Go는 정적 타입언어이다. js처럼 동적으로 선언한 타입이 변하지 않는다. 그렇기 때문에 basic type은 꽤나 중요하다.
Go의 Basic Type들은 꽤나 c/c++과 닮았다. 정리하면 다음과 같다.
- 정수형 : int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uinptr
- 바이트 : byte 라고 쓰지만 내부적으로 uint8과 같다.
- 문자 : '' 로 표현하며 rune 이라고 표현한다. 내부적으로 int32와 같다.
- 문자열 : ""로 표현하며 string 으로 쓴다.
- 실수형 : float32, float64
- boolean : bool
- 복소수 : complex64, complex128
특이한 점을 짚어보자
- 문자(rune) vs 문자열
rune은 '룬'이라고 읽고 보통 우리가 생각하는 문자와 같다. 따라서 '' 로 표현한다.
우리가 생각하는 문자와 같기 때문에 이 역시 내부적으로 유니코드를 가리키고 있어 rune을 출력하면 숫자가 나온다.package main
import (
"fmt"
)
func main() {
fmt.Println('c') // 99
}
문자열은 "" 으로 표현한다. 재밌는 것은 문자열 string의 각 값들을 출력하면 rune과 같이 출력된다.
```go
package main
import (
"fmt"
)
func main() {
var str string = "cibal"
fmt.Println('c') // 99
fmt.Println(str[0]) // 99
}
그러나 c/c++ 처럼 string의 각 요소들을 변경할 수는 없다. 자바처럼 str[0] = 'w'로 접근하면 에러가 발생한다.
- complex
복소수형을 지원한다는데, 사실 써본 적이 없어서 묵혀두었다가 나중에 보자
6. 변수 선언하기
Go에서 변수란 값을 가지고 있는 저장소이다. 변수 선언을 통해 변수에 이름을 부여할 수 있다.
재미있게도 var 이라는 키워드를 사용하는데 정적 타입 언어이다!
var 변수이름 타입 = 값
매우 희안한 구조를 가지고 있다.
typescript나 kotlin과 엇비슷하면서도 다르다.
아래는 typescript의 변수 선언이다.
let variable : string = "typescript"
golang은 다음과 같다.
var variable string = "go"
변수를 만들었으니 사용해보자
package main
import "fmt"
func main() {
var variable string = "go"
fmt.Print(variable) // go
}
아 추가적으로 golang은 절대절대 한 번도 사용되지 않는 변수가 존재하는 것을 허용을 해주지 않는다.
즉, 변수를 만들었다면 반드시 어느 곳에서 한 번이라도 쓰여야 살아남는다. 아니면 컴파일 에러가 난다. 대부분의 언어에서는 warning이 발생하는데 아주 깐깐하다.
6.1 디폴트
변수 선언 시 값을 초기화해주 읺으면 다음의 디폴트 값이 들어간다.
- 정수, 실수 : 0
- 문자열 : 빈 문자열("")
- bool : false
package main
import "fmt"
func main() {
var str string
var boolean bool
var digit int
var sosu float32
fmt.Println(str) //
fmt.Println(boolean) // false
fmt.Println(digit) // 0
fmt.Println(sosu) // 0
}
6.2 단축 변수 선언
이거 참 기가막히다. 처음보는 사람들은 기절초풍할 문법이라서 눈이 휘둥글해진다.
변수를 선언할 때 선언과 동시에 값을 할당하는 경우에는 보통 "단축 변수 선언"을 사용한다. 변수의 타입을 명시적으로 선언하고, 나중에 값을 할당하는 대신 := 연산자를 이용하여 선언과 초기화 작업을 동시에 하는 것이다.
package main
import "fmt"
func main() {
quantity := 4
length, width := 1.2, 2.4
customerName := "su lee"
fmt.Println(quantity) // 4
fmt.Println(length, width) // 1.2 2.4
fmt.Println(customerName) // su lee
}
자동으로 들어가는 값에 따라 타입을 정해준다. 따라서 만약 다른 타입의 값을 넣으려고 한다면 에러가 발생하게 된다.
맨 처음에는 어색하지만 좀 쓰다보면 이렇게 편할 수가 없다.
6.3 네이밍 규칙
GO에는 함수, 변수, 타입을 명명하는데 간단한 규칙들이 있다.
- 이름은 문자로 시작해야하며, 임의 개수와 문자와 숫자로만 구성한다.
- 변수 , 함수, 타입의 이름이 대문자로 시작하면 노출되어 외부 패키지에서 접근할 수 있다. 그래서 fmt의 Println이 앞이 대문자인 것이다. 반면에 소문자로 적시할 시에는 외부로 노출되지 않는다.
6.4 타입 변환
Go에서는 수학 및 비교 연산에는 동일한 타입의 값만 사용할 수 있다. 따라서 타입이 다른 경우에는 에러가 발생한다.
따라서, float32와 int를 비교하거나, string과 int를 비교하면 에러가 발생한다.
package main
import "fmt"
func main() {
quantity := 4
length := 1.2
fmt.Println(quantity * length) // invalid operation: mismatched types int and
}
또한, 변수의 타입이 다른 값을 할당하려고 하면 에러가 발생한다. 때문에 타입 변환이 필요한 것이다.
타입 변환 방법은 매우 간단한데
바꾸려는타입(변수)
이다.
package main
import (
"fmt"
"reflect"
)
func main() {
quantity := 4
length := 1.2
fmt.Println(quantity * int(length))
fmt.Println(float64(quantity) * length)
fmt.Println(reflect.TypeOf(quantity))
fmt.Println(reflect.TypeOf(float64(quantity)))
}
reflect.TypeOf(변수)를 통해서 변수의 타입도 알 수 있다. 중요한 것은 이렇게 타입 변환 시에는 변수의 타입 자체를 바꾸는 것이 아니라, 타입을 바꾼 결과를 리턴한다는 것을 알아두자
따라서 float64(quantity) 를 한 번했음에도 quantity는 int형이 나오는 이유가 바로 그것이다.
또한, 실수형을 정수로 바꾸면 여타 다른 언어와 마찬가지로 소수부가 사라지는 내림 현상을 사용한다.
참고로 정수형, 실수형끼리 크기 비교도 안된다.
package main
import (
"fmt"
)
func main() {
quantity := 4
length := 1.2
fmt.Print(quantity < length)
}
에러가 발생할 것이다.
오늘은 여기까지만 맛보기를 하고 뒤에서 더 자세히 알아보도록 하자