아 이거 새로 카테고리 만들까? 일단 etc에 놔두고 나중에 옮기던가 해야겠다.
무슨 게시물을 쓰든 잡담으로 시작하는 내 블로그,,,
오늘도 게으른 나를 붙잡아주는 멋쟁이 덕분에 어쩌다가 Go Lang Study를 시작하게 되었다.
이거 한다고 내가 당장 Go 전문가가 되는 건 아니니까 나중에 Go를 따로 공부한다고 하면 도움이 될 것 같다.
일단 기초 문법부터 후루룩 훑었는데, 뭔가 이것저것 짬뽕된 느낌도 있고 새로운 느낌도 있고 그렇네요!
유구한 C++ 바보라 C++과 자꾸 비교하게 되는 점 이해해주셍요
C++ 잘 하지도 못하면서 맨날 왜 그러는지 모르겠당,,, 약간 처음 본 사람을 `엄마로 여기는 아기오리 느낌,,,ㅋㅋ
Intro
Go는 구글에서 개발한 언어이다. 나중에 이 팀에서도 일해보고 싶다는 마음이 아츄참캰 들었다.
C++/ Java/ Python 의 장점을 뽑아 만들어졌는데, 불필요한 것들은 없애 버리고 25개의 키워드만으로 프로그래밍이 가능하게 하였다. 큰 특징 중 하나로, CSP ( Communicating Sequential Process) 스타일의 Concurrent Programming이 가능하게 한다는 점이 있다.
Variables & Constants
Variables
변수 선언이 조금 특이하다.
var <변수명> <type> = <초기값> 요런 느낌
var a int
var f float32 = 11.
var i,j, k int = 1, 2, 3
var d = 5
타입을 생략할 수도 있긴하다. 타입 추론이 가능하기 때문인데, 이는 Go가 initial value를 통해 타입을 추론해서 타입을 지정하기 때문이다. 다라서 타입을 생략할 때는 initialization을 해주어야 한다.
Short Assignmetn Statement (:=)를 사용할 수 도 있다. 근데 이건 지역변수 선언할 때만 가능하다.
Constants
const 키워드를 사용하여 상수를 선언한다. 걍 맨 앞에 var 대신 const 붙이면 됨.
여러개 묶어서 한번에 const 지정할 수 있음.
const hi = "Hi"
const (
Sky = "Blue"
Rose = "Red"
Gyuri = "Awesome"
)
iota 라는 identifier 사용하면 상수값을 순차적으로 0부터 부여할 수 있다.
iota가 무슨 뜻인고 했는데 abbreviation이 아니래서 좀 놀랬다. 그냥 뭐.. 적은양의 뭐라는데 나도 잘 모르겠음.
나는 나 혼자 생각에 Increasing Order to Ascii 뭐 이런건가 했네
const (
apple = iota
grape
orange
)
Data Type
다른 언어와 별 다른 건 없는듯 하다.
하지만 사이트에서 string에 관한 건 따로 섹션까지 만들어 설명해줬으니 조금 짚고 넘어가자.
String
Back Quote(``)와 Double Quote("")로 선언할 수 있다. (single quote ('') 안 씀 )
Back Quote로 쓰인 문자열은 Raw String Literal 로서, 문자열이 별도로 해석되지 않는다. 예를들어, '\n'은 new line으로 해석되지 않고, 문자 그대로 사용된다.
Double Quote가 흔히 (내가) 알고 있는 문자열인 Interpreted String Literal 이다.
rawLiteral := `메롱메롱\n`
interLiteral := `얼레리꼴레리\n`
아 그리고 String은 immutable type이다. 한번 생성되면 수정할 수가 없다.
나는 Java도 그렇고 왜 string을 자꾸 불변으로 만드는지 모르겠다. 그게 더 좋은 점이 있겠지만 나는 싫어억!!!
Type Conversion
Go에서는 암묵적인 type conversion이 이뤄지지 않는다. 항상 명시적으로 지정해 주어야 한다.
Type(var)와 같이 표현한다.
func main() {
var i int = 100
var u uint = uint(i)
var f float32 = float32(i)
println(f, u)
str := "ABC"
bytes := []byte(str)
str2 := string(bytes)
println(bytes, str2)
}
근데 좀 웃긴게, 명시적인 type conversion 이 없을 때 compile err가 발생하는 것이 아니라, runtime err가 발생한다.
나 같은 사람은 이렇게 런타임에러 나면 하루종일 이것만 찾을 수 있을 것 같다...
Operator
C++에서 쓰는 거 다 된다. 파이썬처럼 불편하게 += 1 안 해도 됨.아 포인터 싫은데 포인터 있는 게 좀..
사용 법은 C와 비슷하고, 포인터 선언할 때 *를 타입 앞에 붙이는 게 조금 다르다.
(For familiarity, Go's pointers use the * notation from C, but we could not bring ourselves to make a similar reversal for pointer types. Thus pointers work like this.. 라는데 뭐.. 해줄거면 좀 끝까지 비슷하게 해주셨어야죠..!ㅜ)
var p *int
var q ^int
var k int = 10
var p = &k //k의 주소를 할당
println(*p) //p가 가리키는 주소에 있는 실제 내용을 출력
*는 multiplication로도 쓰여서 대신 ^를 쓰기도 한다는데 굳이,,, 정석대로 써서 광명 찾자!
조건문
if/else
1. if 다음에는 반드시 Boolean식으로 표현한다. (0, 1 이런거 못 씀)
2. () 안 쓰지만 {}는 무조건 써 줌.
3. else if 혹은 else 를 쓸 때는 반드시 전 조건의 open braces( { )와 같은 라인에 써준다.
if k == 1 {
println("One")
} else if k == 2 { //같은 라인
println("Two")
} else { //같은 라인
println("Other")
}
재밌는 게 하나 추가 된다. if문에서 for문 처럼 Optional Statement를 사용할 수 있다.
Conditional Statement와는 세미콜론으로 구분해준다.
if val := i * 2; val < max {
println(val)
}
Switch / Case
C++의 switch 와는 좀 다른 점이 있다.
C++ 의 switch는 case블럭 안에 break를 써주어서 switch문을 빠져나와야 하고, break를 써주지 않는다면 다음 case 블럭에 들어간다. Go에서는 그렇지 않고, 하나의 case 에 만족한다면 그 블럭을 실행하고 바로 switch문을 빠져 나온다.
만약 C++ 의 switch처럼 다음 case 블럭들에도 들어가게 하고 싶다면 fallthrough 를 써주면 된다.
func check(val int) {
switch val {
case 1:
fmt.Println("1 이하")
fallthrough
case 2:
fmt.Println("2 이하")
fallthrough
case 3:
fmt.Println("3 이하")
fallthrough
default:
fmt.Println("default 도달")
}
}
근데 C++ 에서 보다는 switch문이 좀 유용해 보인다.
먼저, case 뒤에 expression 없애서 if/else if/ else 문장을 단순화 시킬 수도 있다.
func grade(score int) {
switch {
case score >= 90:
println("A")
case score >= 80:
println("B")
case score >= 70:
println("C")
case score >= 60:
println("D")
default:
println("No Hope")
}
}
심지어 변수의 type 을 검사할 수도 있다!
switch v.(type) {
case int:
println("int")
case bool:
println("bool")
case string:
println("string")
default:
println("unknown")
}
Loop
for
while은 없고 for 만 있다.
역시 () parentheses 는 사용하지 않는다. 다음과 같이 사용한다.
for i := 1; i <= 100; i++ {
}
for n < 100 { // while문 역할
}
for { // 무한반복
}
python처럼 for range 문이 사용가능하다.
근데 index 변수까지 변수가 2개 필요.
names := []string{"진명아", "나도", "숙제 시작했어"}
for index, name := range names {
println(index, name)
}
break <Label> 이 있다.
반복문을 탈출해서 <Label>로 간다음, for문을 건너 뛰고 그 다음 문장을 실행한다.
package main
func main() {
i := 0
L1:
for {
if i == 0 {
break L1
}
}
println("OK")
}
여기서는 println으로 바로 가서 OK 출력하고 끝남.
Collection
순서를 좀 바꿔서 Collection으로 먼저 가볼까 한다.
Array
언제나 그렇듯 zero base
선언은 var <변수 이름> [배열크기]<type>
여기서 배열크기 또한 type을 구성하는 요소이다. [3]int와 [5]int는 다른 타입의 변수이다.
var a [3]int
var a1 = [3]int{1, 2, 3}
var a3 = [...]int{1, 2, 3} //배열크기 자동으로
var a = [2][3]int{
{1, 2, 3},
{4, 5, 6}, //끝에 콤마 추가
}
Slice
전체적으로 벡터와 비슷한 개념으로 이해했다.
선언은 배열과 똑같이 하는데, 대신 [] 안에 크기는 지정해주지 않는다.
func main() {
var s []int
var a []int{1, 2, 3}
if s == nil {
println("Nil Slice")
}
println(len(s), cap(s)) // 모두 0
}
make라는 함수를 이용해 slice를 만들어 줄 수도 있다.
a := make([]int, 5, 10) // slice with len :5, capacity : 10
파이썬처럼 index를 활용해 sub slice를 만들어 줄 수 있다.
언제나 그렇듯 slice[start idx : end idx +1 ] 되어 주시겠다.
s := []int{0, 1, 2, 3, 4, 5}
s = s[2:5] // 2, 3, 4
s = s[1:] // 3, 4
slice와 slice는 append()를 사용해 연결할 수 있다.
주의할 점은 붙일 slice 중 두번째에 ellipsis(...)를 붙여야 한다는 것.
Go에서의 ellipsis는 여러 의미로 사용되는데, 여기서는 "unpacking" 의 의미이다. 해당 slice의 컬렉션을 표현하는 것( slice의 모든 element들의 집합)이래서 뭔가 했는데, 대충 slice에 있는 element들을 unpack해서 append같은 variadic function에 넣어준다는 것 같음.
package main
import "fmt"
func main() {
sliceA := []int{1, 2, 3}
sliceB := []int{4, 5, 6}
sliceA = append(sliceA, sliceB...)
//sliceA = append(sliceA, 4, 5, 6)
fmt.Println(sliceA) // [1 2 3 4 5 6] 출력
}
copy()를 활용하여 복사할 수도 있다.
source := []int{0, 1, 2}
target := make([]int, len(source), cap(source)*2)
copy(target, source)
Map
드디어 Hashtable! 다음과 같이 두 가지 방법으로 선언할 수 있다.
map[key type]value type
var idMap map[int]string
idMap = make(map[int]string)
후에 Go interface에서 다룰건데, 이걸 활용하면 python의 dict처럼 사용할 수 있다.
Map에서 특정 key가 존재하는지를 체크하는 방법은 다음과 같다.
map변수 [key] 읽기를 수행할 때 2개의 리턴값이 있는데, 이 때 두번째 값이 그 키가 존재하는지 나타내는 bool값이다. 이 것을 체크해주면 된다.
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")
}
}
사실 value값의 범위에 0만 포함되지 않으면 key에 해당하는 value가 0인지 아닌지만 체크하면 된다. 만약 value가 reference라면 nil인지만 체크하면 된다. 하지만 이건 범용적인 범위가 아니므로 패스
+Map은 unordered인 hash이므로 순서가 무작위이다. 따라서 for range를 이용했을 때 모든 매 요소가 매번 다른 순서로 반복문에 돌려진다.
아 정리할라니까 너무 많은데...
함수부터는 따로 하는 게 나을 것 같다. 근데 뒤에는 내용 쵸큼 어려워지는데 언제 하냐
출처 :
예제로 배우는 Go 프로그래밍
쉽고 재미있는 Go 프로그래밍 예제로 배우는 Go 프로그래밍 I like a lot of the design decisions they made in the [Go] language. Basically, I like all of them. - Martin Odersky, Creator of Scala
golang.site
The Go Programming Language Specification - The Go Programming Language
The Go Programming Language Specification Version of Jan 14, 2020 Introduction This is a reference manual for the Go programming language. For more information and other documents, see golang.org. Go is a general-purpose language designed with systems prog
golang.org
'CS > Go' 카테고리의 다른 글
Go Lang - Package ~ Interface (580) | 2020.05.05 |
---|---|
Go Lang - Function (700) | 2020.05.05 |