반응형

개요

고에서는 array, slice, map을 지원한다

 

slice는 가변적인 배열로 , 파이썬에서는 list

map은 key-vaule 의 형태의 자료형으로 dict로 생각하면 된다. 

 

slice와 map은 함께 많이 사용한다. 어떻게 사용하는지 정리해본다. 

 

배열

package array

import "fmt"

func NewArray(){
	var a [5]int // 다른 데이터 형태와는 달리 var 변수명 뒤에 자료형을 생략할 수 없음
	b := [4]int{1,2,3,4} //배열은 선언과 동시에 초기화가 가능

	fmt.Println(a,len(a))
	fmt.Println(b, len(b))
}

[0 0 0 0 0] 5 // 값을 지정하지 않으면 0 으로 초기화
[1 2 3 4] 4

 

슬라이스

package slice


func NewSlice(){
	// slice 선언 두가지 방법으로
    var a []int
    b := make([]int,5,10)
    //int 자료형인 길이 5, 최대 길이 10 
     
    //즉, slice는 고정길이 배열과 달리 초기화시 최대 길이를 지정할 수 있고,
    //해당 slice를 통해 최대 길이를 넘지 않는 범위에서 가변길이 배열(=슬라이스)을 얼마든 생성해낼 수 있다

	//append같은 메소드를 사용하면 슬라이스의 길이를 확장시킬 수 있다
    b = append(a, 5,2,3,4)
    fmt.Println(a,b)
}

[] [5 2 3 4]

 

슬라이스와 배열의 차이는 가변 길이를 정하는 것이고, 

리스트 선언 시 길이를 명시해주면 배열(생성한 길이 만큼만 사용할 수 있음)

길이를 명시하지 않으면 슬라이스(유연하게 조정하고 늘려가며 사용할 수 있음)

 

package map1

import "fmt"


func NewMap(){
	// 주어진 타입을 초기화하고 사용할 수 있는 맵을 반환
	
	a := make(map[int]string)
	a[1] = "A"
	a[2] = "B"

	// 초기화 시 값을 넣어서 맵을 반환할 수 있음 
	map_int_str := map[int]string {
		1: "월",
		2: "화",
		3: "수",
		4: "목",
		5: "금",
		6: "토",
		7: "일",
		//마지막 값 입력 시에도 , 가 빠지면 에러
		}

	fmt.Println(a,map_int_str)
	//map[1:A 2:B] map[1:월 2:화 3:수 4:목 5:금 6:토 7:일]
}

만약 없는 요소라면? 숫자일 경우에는 0을 문자열의 경우에는 "" 을 출력한다 

 // 만약, 값이 주어지지 않은 요소를 꺼내온다면?

package map1

import "fmt"

func NotInMap(){
	a := make(map[int]int)

	a[1] = 2
	a[3] = 4

	fmt.Println(a[2])
}
// 0

 

정확히 맵은 어떤 타입을 반환하는걸까 보면 

package map1

import "fmt"

func NotInMap(){
	a := make(map[int]int)

	a[1] = 2
	a[3] = 4

	value1, ok := a[1]
	fmt.Println(value1,ok)
	// 2 true

	value2, ok := a[2]
	fmt.Println(value2,ok)
	// 0 false 

	value3,ok := a[3]
	fmt.Println(value3,ok)
	// 4 true
}

존재하지 않는 키 값을 요청한다면, 두 번째 인자로 false 를 반환한다. 

아래는 맵의 요소 확인과 삭제 문법

package map1

import "fmt"

func NotInMap(){
	a := make(map[int]int)

	// 맵에 요소를 추가하거나 업데이트 
	a[1] = 2
	a[3] = 4

	value1, ok := a[1]
	fmt.Println(value1,ok)
	// 2 true

	value2, ok := a[2]
	fmt.Println(value2,ok)
	// 0 false 

	// 요소 제거 
	delete(a,3)

	value3,ok := a[3]
	fmt.Println(value3,ok)
	// 0 false
}

 

따라서 go에서는 아래와 같이 예외 처리를 한다. 

 

package map1

import "fmt"

func NotInMap(){
	a := map[int]int{
		1 : 2,
		2 : 3,
		3 : 4,
		4 : 5,
	}
	
	// key를 0~7까지 대입하고, a[key] 의 결과로 ok 값을 받아 
	//ok가 true일 경우(해당 키에 대한 value값 존재 시 ) key에 해당하는 value를 출력
	//그렇지 않을 경우(false/ value값이 미존재 시 ) 문자열 출력
	for key:= 0; key < 8; key++{
		if value, ok := a[key];ok{
				fmt.Println(value)
			} else {
			fmt.Println("key", key, "is not exist")
		}
	}
}

key 0 is not exist
2
3
4
5
key 5 is not exist
key 6 is not exist
key 7 is not exist

 

go tour > 맵 연습하기 (링크 : https://go-tour-ko.appspot.com/moretypes/23) 

// go tour map 연습하기

// 문자열 s가 주어진다
//주어진 문자열을 단어 단위로 나눠 단어가 몇번 쓰였는지 맵으로 기록한다
// wc.test 함수로 우리가 작성한 함수를 여러 테스트 케이스로 테스트해준다.

package map1

import (
	"strings"

	"golang.org/x/tour/wc"
)

func WordCount(s string) map[string]int {
	//strings filed는 유니코드에서 정의한 대로 
	//하나 이상의 연속된 공백 문자의 각 인스턴스를 기준으로 문자열 분할
	words := strings.Fields(s)
	//일단 문자열을 단어 단위의 배열로 반환 

	result := make(map[string]int)

	// for 인덱스 , 요소 := range 배열 {...}
	// 아래는 요소만 사용할 때 
	for _, w:= range words{
		if result[w] == 0 {
			result[w] = 1
		}else{
			result[w] = result[w] +1
		}
	}
	return result
}


func main() {
	wc.Test(WordCount)
}

//PASS
 f("I am learning Go!") = 
 map[string]int{"Go!":1, "I":1, "am":1, "learning":1}
PASS
f("The quick brown fox jumped over the lazy dog.") = 
 map[string]int{"The":1, "brown":1, "dog.":1, "fox":1, "jumped":1, "lazy":1, "over":1, "quick":1, "the":1}
PASS
f("I ate a donut. Then I ate another donut.") = 
 map[string]int{"I":2, "Then":1, "a":1, "another":1, "ate":2, "donut.":2}
PASS
f("A man a plan a canal panama.") = 
 map[string]int{"A":1, "a":2, "canal":1, "man":1, "panama.":1, "plan":1}

 

반응형

'Language Study > Go' 카테고리의 다른 글

[Golang]Method  (0) 2022.12.14
[Golang]Quick sort(퀵 정렬)  (0) 2022.12.13
[Golang]bubble sort(버블 정렬)  (0) 2022.12.13
[Golang]변수, 상수  (0) 2022.08.21
[Golang]클래스, 구조체, 인스턴스  (0) 2022.08.08
반응형

Go는 정적타입 언어 

정적 타입은 컴파일 타임에 타입이 결정되며 런타임 중에 동적으로 타입이 변경될 수 없다 

대신 빠름(왜? 런타임 중에 타입 추론하거나 다시 최적화를 해야할 필요는 없기 때문에)

 

변수

값을 담는 공간 

변수 이름은 문자 

변수의 초기화는 런타임에 동작 / 사용하지 않는 변수가 있는 경우 에러를 뱉는다. 

또 변수를 선언만하고 명시적으로 초기화 하지 않은 상태에서 디폴트로 할당되는 값은 제로값 / int타입은 0  / 각 타입별 제로값 확인하는 함수는 Go IsZero()

구분자료형제로값
숫자형 int, float64 0
불리언 형 bool false
문자열 string "" (빈 문자열)

 

전역 변수 선언

전역 변수는 함수 내에서 선언하는 것과 달리 단축 구문(:=)을 사용하면 에러 

package main

import "fmt"

var hi string = "hi" // 가능
var hello = "hello" // 가능

goodbye := "goodbye" // 에러 발생

func main(){
    //
}

 

함수 외부에서는 모든 문장이 var , func 같은 키워드로 시작되므로 키워드가 없는 단축 구문은 외부에서 사용할 수 없음

 

여러 개 변수 선언

변수를 여러 개 선언하고 초기화 할때는 반드시 선언하는 벼눗와 초기화 하는 값의 개수가 같고, 타입은 같지 않아도 된다. 

package main

import "fmt"

func main(){
    hi, hello, goodbye := "hi", "hello", "goodbye"
}
 

 

var()을 이용해서도 여러 개 변수 선언 가능 

어떨 때 쓰는지? → 연관성 있는 변수 한번에 선언하기 위해서

package main

import "fmt"

func main(){
        var (
        i = 10
        j = 20
    )
}

 

변수 재할당 , 선언

아래 코드 상으로는 m 변수가 재선언하고 값이 변경됨 

정확히는 재선언은 아니고 string으로 m이 이미 선언되어있기 때문에 값만 변경된 것

package main

import "fmt"

func main() {
    m := "hello"
    m, i := "hihi", false

    fmt.Println(m, i)
}

>>hihi false

 

단축 변수 선언 할때 여러 개의 변수를 함께 선언할때 하나라도 새로운 변수가 있으면 

단축 변수 선언 문법을 사용하더라도 기존 변수에 대해서는 재할당 처리 

package main

import "fmt"

func main() {
    m := "hello"
    m := "hihi"

    fmt.Println(m)
}

>># command-line-arguments
.\test.go:12:4: no new variables on left side of :=

만약,

    m := "hello"
    m = "hihi"
로 :가 제거되면 재선언이 되지 않고 값만 변경되기 때문에 hihi 출력

Type 변환

다른type의 요소들 간의 할당에는 명시적인 변환 필요

package main

import (
    "fmt"
    "math"
)

func main() {
    var x, y int = 3, 4
    var f  = math.Sqrt(float64(x*x + y*y))
// /만약 float64 명시적 타입 선언을 제거하면? 에러 발생  prog.go:10:21: cannot use (x * x + y * y) (value of type int) as type float64 in argument to math.Sq
    fmt.Println(x, y, f)
} -> 3 4 5

 

이름 쉐도잉

패키지, 타입과 똑같은 이름의 변수를 선언해도 에러나지않는다. 

package main

import "fmt"

func main() {
    string := 10

    fmt.Print(string)
} --> 해당 코드는 정상 출력하지만 (10)

package main

import "fmt"

func main() {
    string := 10
    var m string
    m = "hi"

    fmt.Print(m)
} --> 해당 코드는 .\test.go:7:6: string is not a type 에러를 뱉는다. 왜? string이라는 변수가 var m 변수에서는 string 타입을 선언하고 있으니까

상수 

한번 선언되고 할당되면 값을 바꿀 수 없다 

선언과 할당을 동시에 진행되어야 하며 const 키워드를 사용하면 상수를 선언 가능 

자료형 명시도 선택적으로 해주면 된다. 어차피 컴파일러가 추론해줌 

package main

import "fmt"

func main() {
    const max_size int = 10
    const max_size = 10 //type 명시 안해도 가능

    fmt.Print(max_size)
}--> 10

여러 상수 선언

변수 처럼 여러개 선언 가능

package main

import "fmt"

func main() {
    const (
        max_size, lang = 10, "golang"
    )
    fmt.Print(max_size, lang)
}10golang

 

반응형

'Language Study > Go' 카테고리의 다른 글

[Golang]Method  (0) 2022.12.14
[Golang]Quick sort(퀵 정렬)  (0) 2022.12.13
[Golang]bubble sort(버블 정렬)  (0) 2022.12.13
[Golang]array, slice, map  (0) 2022.12.04
[Golang]클래스, 구조체, 인스턴스  (0) 2022.08.08

+ Recent posts