사실 프로그래밍 언어를 이 한 페이지에 다 쓴다는 거는 좀 오버인 것 같다 생각한다.
그래서 이 강의를 들으면서 내가 기존에 자주 접해오던 언어(python, c++) 과 어떤 부분이 쓸 떄 좀 특이했는지 이런 점을 위주로 써 보고자 한다.
그리고 오늘내로 이제 GO를 이용해 해볼 토이프로젝트를 생각해 봐야겠다.
GO에서의 변수 선언은 되게 특이했었다. 보통 Java 나 C++ 에서 변수를 선언한다면
int val = 10
이런 순서대로 자료형 다음 변수 이름을 선언을 하는데 Go 같은 경우는
var val int
var val = 10
val := 10
이런식으로 변수를 선언하더라 아래 두개는 뭐 익숙한 형식이지만 맨 처음 방식은 잘 익숙해지지가 않더라.
또한 GO에서는 변수를 선언하거나 라이브러리(?) 패키지를 import 하고 사용하지 않는다면 컴파일을 할 때 에러를 뿜뿜 해준다.
이 점이 이 언어가 뭔가 깔끔한 코드 작성하도록 의도하는 느낌이 든다.
평소에 나는 코딩을 할 때 습관이 뭔가 이것 저것 선언하다가 지우고 나중에 안쓰는 라이브러리를 잘 정리를 안하는데, 애초에 컴파일 할 때 이러니 자동으로 조심하게 되는점이 좋다면 좋다고 할 수 있겠다...
자료형에 대해서는 별로 할 말 이 없다. 파이썬보다 없다면 없지 뭔가 더 편리한 자료형이 있다는 생각이 들지는 않는다. 그렇다고 부족하다는 생각은 또 들지는 않는다.
익숙해 질겸 Go로 알고리즘 문제를 요즘 풀고 있는데, 주로 파이썬 쓰다가 Go를 쓰니 은근 불편할 때가 있다.
파이썬 같은 경우는 아무래도 알고리즘 문제를 풀때 defaultdict 같은 자료형도 잘 되어 있고, 함수나 연산자도 이거저것 많아 쓰기 편하다.
하지만 Golang 에서는 쉽고 간결한것이 지향점인지 은근 내장함수가 적은 듯 싶다.. 물론 내가 아직 공부를 많이 한 것이 아니라 적은 것일 수도 있다.
이건 기억해두면 자주 쓸 듯 싶어 적어놓고자한다.
const (
_ = iota // 첫줄 무시
KB = 1 << (10 * (1 + iota))
MB
GB
TB
PB
EB
ZB
YB
)
파이썬의 list, c++의 벡터에 길들여져 있다가 오랜만에 배열에 크기 제한이란거를 겪어보니 순간 적응이 안됐다.
사실 적응이 안됐다는 거도 말이 안되는 변명이다. 애초에 c++ 이나 java는 배열을 선언하면 사이즈도 지정하니깐 말이다 ㅋㅋㅋ
보통 아래의 방식으로 배열을 지정한다.
arr := [3]int
arr := [3]int{1, 2, 3}
arr := make(int[], size)
arr := make(string[], length, capcity)
뭐 이건 자주 써본다면 익숙해질 문제라고 생각한다.
파이썬에서 쓰면 dict 이고 c++ 에서 쓰면 hashmap인 그 자료형이다 뭐 사용법만 적고 넘어가면 될 것 같다.
val := make(map[string]int)
이것도 뭐 사실 그렇게 크게 다르다고 느낀 것은 없었다.
type Bird struct{
name string
canFly bool
speed float32
}
뭐 GO 소개문에서 나오길 Go에는 do while도 While도 foreach 도 없고 for만 있다는 말을 보았다.
for 만 있긴 하다 물론 for 만 쓰진 않고 range를 써서 파이썬의 for in
for i in arr:
print(i)
처럼 인덱스말고 값을 가져와서 for문을 사용하는 방법도 있었다.
for i:=0 ; i < len(arr); i++{
fmt.Println(arr[i])
}
for i:= range arr{
fmt.Println(i)
}
// 둘다 arr이라는 배열에 저장된 값을 출력하는 건 똑같다.
요즘 언어들은 뭔가 pointer를 잘 안쓰는 느낌이 있는데 얘는 포인터가 있었다. 포인터라는 개념은 여기서 설명할만한 주제는 아니니까 넘어가겠다.
다른 언어에도 이런게 있나 싶은 느낌의 개념인거같다. 물론 다른 언어에서도 try ~ finally같은 개념은 있다.
스코프로 감싼 다음에 finally 스코프에 함수를 적는다면 마지막에 작동한다.
하지만 defer 는 그냥 함수 앞에 defer를 마지막에 적어주면 그냥 실행된다. 중간에 에러가 발생해도 마지막에 꼭 실행하고 끝난다.
func main(){
defer fmt.Println("first")
fmt.Println("second")
}
이렇게 실행한다 치면 결과는
second
first
이렇게 나올 것이다. 뭐 실제로 코딩에서 사용한다면...
파일 작업을 할 때 defer 를 사용해 close 하면 무조건 에러가 있더라도 파일을 닫는 작업을 수행한다.
panic은 현재 함수를 멈추고 현재 함수에 defer 함수들을 모두 실행하고 즉시 return 한다.
이 panic은 콜스택을 타고 올라가면서 적용된다.
예를들어
func exam(val String){
f, err := os.Open(fn)
if err != nil{
panic(err)
}
// 이 출력문은 실행되지않고
fmt.Println("v파일 오픈!")
// 이 defer 함수가 실행되고 return 된다.
// 그리고 프로그램이 종료할 때 까지 계속 콜스택을 타고올라가며 적용된다.
defer f.Close()
}
recover 는 panic 상태일 때 다시 정상 상태로 돌리는 함수다.
이것은 좋은 예제가 있어서 가져왔다.
package main
import (
"fmt"
"os"
)
func main() {
// 잘못된 파일명을 넣음
openFile("Invalid.txt")
// recover에 의해
// 이 문장 실행됨
println("Done")
}
func openFile(fn string) {
// defer 함수. panic 호출시 실행됨
defer func() {
if r := recover(); r != nil {
fmt.Println("OPEN ERROR", r)
}
}()
f, err := os.Open(fn)
if err != nil {
panic(err)
}
defer f.Close()
}
함수에 관해서는 그냥 예제만 적고 넘어가겠다.
func divide(a, b float64) (float64, error){
if b == 0.0 {
return 0.0 fmt.Errorf("Cannot divide")
}
return a / b, nil
}
이 세개에 관해선 약간 Go 에서 중요하게 써야할 것 같은 개념이라 이 페이지에 적기는 양이 너무 많다고 생각이 든다.
그래서 그냥 이건 다른 페이지에서 날을 잡고 정리를 해 두는 것이 더 낫다고 생각이 든다.
강의를 들으면서 Go가 가지는 장점을 느낄 수 있는 시간이었다.
아무래도 컴파일을 하는 언어이다보니 속도도 파이썬 보다 빠르다.
그러면서 C언어나 c++ 언어보다는 굉장히 간단하게 학습가능했던 언어였다.
그런데 뭔가 설명할 순 없지만 애매하단 느낌이... 있긴하다.
일단 어떤 프로젝트를 할 지 생각을 하고 진행해 봐야겠다...