Variables
Go언어의 상수, 변수 선언은 JS(JavaScript)와 TS(TypeScript)의 중간에 있다는 느낌을 받았다. TS처럼 type을 명시하는 것을 기본으로 하고 JS처럼 타입을 명시하지 않고 빠른 개발이 가능하도록 축약형을 제공한다. 하지만, 축약형은 상수가 아닌 변수일때만 가능하고 처음 초기화된 type에서 다른 type으로의 변경을 허용하지 않는다. JS와 같은 편리함은 있지만 그래도 엄격하다.
func main() {
/* literal */
const firstName string = "jisung"
/* variable */
var lastName string = "jung"
lastName = "kim"
/* 축약형 - 변수에만 사용 가능 */
greeting := "Hello,"
fmt.Println(greeting, firstName, lastName)
}
//output:
//Hello, jisung kim
Go Basic Types [https://go.dev/tour/basics/11]
Function
함수에서는 자바에서 활용하던 가변인자를 볼 수 있어서 익숙함을 느꼈다. Go언어의 함수 부분에서 가장 놀랐던 부분은 복수개의 값을 return 하는것이 가능하다는 것이었다. 평소 여러개의 값을 return하고 싶은 경우가 많았지만, Java에서는 불가능해 배열이나 자료구조를 활용하는 방법을 많이 채택했었고 이를 지원하는 는 다른 언어 또한 찾을 수 없었다. Go는 이게 가능하다니 신기하고 자주 활용할 것 같다.
/* basic - define parameter type and return type */
func multiply(a int, b int) int {
return a * b
}
/* multiple return value */
func lenAndUpper(name string) (int, string) {
return len(name), strings.ToUpper(name)
}
/* varargs in Go */
func repeatMe(words ...string) {
fmt.Println(words)
}
func main() {
const firstName string = "jisung"
fmt.Println(multiply(2, 5))
totalLen, upper := lenAndUpper(firstName)
fmt.Println(totalLen, upper)
repeatMe("A", "B", "C")
}
//output:
//10
//6 JISUNG
//[A B C]
Loop
반복문은 range라는 키워드가 있어 파이썬을 보는 것 같았다. '_' 라는 키워드가 있는데 이는 컴파일 과정에서 해당 값을 무시하는 용도로 쓰인다고 한다. 규칙을 지키면서 유연한 코드를 작성할 수 있도록 도와주는 것 같다. Go가 빠른데에는 이유가 있구나라는 생각이 들었다.
func superAdd(numbers ...int) int {
for index, number := range numbers {
fmt.Println("index:", index, "number:", number)
}
fmt.Println("==========================")
for i := 0; i < len(numbers); i++ {
fmt.Println("index:", i, "number:", numbers[i])
}
total := 0
for _, number := range numbers {
total += number
}
return total
}
func main() {
var result int = superAdd(1, 2, 3, 4, 5)
fmt.Println("result:", result)
}
//output:
//index: 0 number: 1
//index: 1 number: 2
//index: 2 number: 3
//index: 3 number: 4
//index: 4 number: 5
//==========================
//index: 0 number: 1
//index: 1 number: 2
//index: 2 number: 3
//index: 3 number: 4
//index: 4 number: 5
//result: 15
If-Else and Switch
조건문의 기본적인 형태는 다른 언어들과 크게 다른 부분이 없었지만, 조건문의 조건부에서 변수를 선언해 사용할 수 있다는 점이 재미있었다. 당연하겠지만, 조건부에 선언한 변수는 조건문 안에서만 사용할 수 있는데 평소 조건문 밖에서 필요한 변수를 만들어 사용할때 코드가 지저분해진다는 느낌을 많이 받은 사람으로서 아주 유용하게 사용할 것 같다.
func main() {
age := 15
canIDrink := false
if age < 18 {
canIDrink = false
} else {
canIDrink = true
}
if koreanAge := age + 2; koreanAge < 18 {
canIDrink = false
} else {
canIDrink = true
}
// switch
switch koreanAge := age + 2; koreanAge {
case 10:
canIDrink = false
case 18:
canIDrink = false
}
switch {
case age < 18:
canIDrink = false
case age == 18:
canIDrink = true
case age > 50:
canIDrink = true
}
fmt.Println(canIDrink)
}
//output:
//false
Pointer
포인터다. 대학교 1학년때 C언어 수업에서 포인터를 배우고 이번 Go언어에서 처음본다. 개인적으로 대학생때 low-level에 대해 공부하는게 좋았기 때문에 당시 포인터 개념을 재미있게 배운 기억이 있어서 잘 활용할 수 있을 것 같다. (그치만 3차원 이상의 다차원 포인터는 지옥이다.) 여기까지 와서 보니까 Go언어는 C언어도 보이고 Java, JS, TS, Python까지 보인다. 이후 나오겠지만 객체 표현을 위한 struct의 개념도 존재한다. 1가지 언어에 다양한 언어의 장점을 녹여낸 것 같고, 강력한 C 베이스에 타 언어의 편리함을 가져온 아주 매력적인 언어라는 생각이 든다.
func main() {
a := 2
b := &a
c := &b
a = 10
fmt.Println("pointerExample1:", &a, b, *c)
fmt.Println("pointerExample2:", &b, c)
fmt.Println("pointerExample3:", a, *b, **c)
*b = 20
fmt.Println("pointerExample4:", a)
}
//output:
//pointerExample1: 0x1400000e0c0 0x1400000e0c0 0x1400000e0c0
//pointerExample2: 0x140000520b0 0x140000520b0
//pointerExample3: 10 10 10
//pointerExample4: 20
Array
일반 배열은 다른 언어와 비슷해 보인다. 길이를 설정하고 index 범위에 맞춰 데이터를 저장할 수 있다. 특이한 점이라고 하면 배열에 길이를 지정하지 않으면 Java Collection의 List처럼 data를 add(append)하는 방식으로 사용할 수 있는데 append함수를 사용하면 값을 추가한 새로운 배열을 받아와 저장한다고 한다. 지금 딱 봤을때는 이 방식이 효율적인지 잘 모르겠다. 그치만, Go언어에서 유용하게 사용하는 방식이라고 하니 좀 더 알아봐야할 것 같다.
func main() {
/* array - 선언과 동시에 초기화 */
alphabets := [5]string{"a", "b", "c", "d", "e"}
fmt.Println(alphabets)
/* array - 배열의 길이만 정의 */
names := [3]string{}
names[0] = "jisung"
names[1] = "ji"
names[2] = "sung"
fmt.Println(names)
/* slice - 길이를 지정하지 않는 배열 - append()를 이용해 받아온 새로운 배열을 저장 */
var numbers []int
numbers = append(numbers, 1)
numbers = append(numbers, 2)
numbers = append(numbers, 3)
fmt.Println(numbers)
}
//output:
//[a b c d e]
//[jisung ji sung]
//[1 2 3]
Map
Go언어에서의 Map도 key-value 형식의 데이터를 저장할 수 있는 자료구조이다. 데이터를 선언과 동시에 초기화 할 수 있고 Go에서 제공하는 make() 함수를 이용해 Map을 생성한 후 데이터를 추가할 수도 있다.
func mapsExample() {
/* 기본 map 선언 */
jisung := map[string]string{"name": "jisung", "age": "26"}
fmt.Println(jisung)
/* make()을 사용해 선언 */
jisung = make(map[string]string)
jisung["name"] = "jisung"
jisung["age"] = "26"
for key, value := range jisung {
fmt.Println(key, value)
}
}
//output:
//map[age:26 name:jisung]
//name jisung
//age 26
Struct
Go언어에서는 Object나 Dictionary의 개념이 없고 C언어와 같이 구조체의 개념이 존재한다. 이것도 C언어때 배우고 Java에 절여져 다뤄본 기억이 없는데 새로 알아가기에 재미있을 것 같다.
func main() {
type person struct {
name string
age int
favFood []string
}
favFood := []string{"apple", "chicken"}
jisung := person{
name: "jisung",
age: 26,
favFood: favFood,
}
fmt.Println(jisung)
}
//output:
//{jisung 26 [apple chicken]}
Reference