Devik0213 / memo

메모
1 stars 0 forks source link

go lang { array, slice, map and function } #19

Open Devik0213 opened 5 years ago

Devik0213 commented 5 years ago

배열

메모리공간에 순차적으로 동일한 type의 데이터를 연속적으로 할당함. (Zero based array)

var a [N]int

다양한 초기화

package main
// https://play.golang.org/p/UoR8ozvEAO_O
import (
    "fmt"
)
func main() {
    var a [3]int  //정수형 3개 요소를 갖는 배열 a 선언
    a[0] = 1
    a[1] = 2
    a[2] = 3
    fmt.Println(a[0]) // 1 

    var a1 = [3]int{1, 2, 3}   //  정적 크기
    var a2 = [...]int{1, 2, 3} //  '...' 자동크기

    fmt.Println(a1)
    fmt.Println(a2[0])
    // 다차원 배열
    var a3 = [2][3]int{ // 2행 3열
        {1, 2, 3},  //1행 3열 # 여러줄 나열이므로, ' , ' 콤마를 사용.
        {4, 5, 6},  //2행 3열
    }
    fmt.Println(a3[1][2]) // 6

    var multiArray [3][4][5]int  
    multiArray[0][1][2] = 10   
    fmt.Println(multiArray)     // [[[0 0 0 0 0] [0 0 10 0 0] [0 0 0 0 0]....
    fmt.Println(multiArray[0][1][2])  // 10

}

배열 순회

다중 리턴을 제공하는것과 유사한것일까??

배열 복사

배열 변수는 배열 전체를 다나태기 때문에, a = b 를 하면 b의 값 전체가 복사된다.

func main() {
    var a1 = [3]int{1, 2, 3}   //  정적 크기
    var a2 = [...]int{5, 6, 7} //  '...' 자동크기
    var a3 = [...]int{5, 6, 7, 1,2,3,4,5,56,7,7,78} //  '...' 자동크기

    fmt.Println(a1)
    fmt.Println(a2[0])

    a1 = a2
    fmt.Println(a1)
    a1 = a3
    fmt.Println(a1) // cannot use a3 (type [12]int) as type [3]int in assignment
        a3 = a1
    fmt.Println(a3) // cannot use a1 (type [3]int) as type [12]int in assignment
}
 > 슬라이스가 필요한 느낌이 온다..

슬라이스

동적으로 크기가 늘어날수 있는 레퍼런스 타입!!!. 슬라이스는 공간을 할당 하는것이다.

  • 초기화 및 make 함수

VALUENAME := make( [] TYPE, LENGHT [, CAPACITY_INT]_ ) LENGTH : index 로 접근 가능. CAPACITY : 총 공간의 크기.

CAPACITY는 LENGTH의 배수인가??? - 내부적 알고리즘으로 크기를 지정한다고하는데..

var a []int   // 배열과 달리 [ ] 빈값. len == 0
slice := make( []TYPE, LENGHT_INT )  // len(slice)=5
slice2 := make( []TYPE, LENGHT_INT _[, CAPACITY_INT]_ )  // len(slice)=5, cap(slice) = 5

슬라이스 값 추가

import ( "fmt" )

func main() { slice := make([]int, 5, 10)

fmt.Println(len(slice), cap(slice), slice)

slice = append(slice, 10, 20, 30, 40, 50)
fmt.Println(len(slice), cap(slice), slice)
slice = append(slice, 60, 70, 80, 90, 100)
fmt.Println(len(slice), cap(slice), slice)
for i := 0 ; i < 10; i++ {
    slice = append(slice, i*10, i*20, i*30, i*40, i*50)
    fmt.Println(len(slice), cap(slice), slice)
}

    slice = append(slice, ...)  

}

![2018-11-27 1 33 04](https://user-images.githubusercontent.com/9497634/49058871-43461180-f249-11e8-9075-683a4e304330.png)

 > 잘 상상이 안된다..

찾아보니, A slice is a descriptor of an array segment.
https://blog.golang.org/go-slices-usage-and-internals
![2018-11-27 1 39 57](https://user-images.githubusercontent.com/9497634/49058987-f3b41580-f249-11e8-80d9-2a2b1cef7c00.png)

### 레퍼런스 타입
  - 슬라이스는 배열의 레퍼런스만 알고있다. 하여 슬라이스 assign을 하여, 값을 수정하는경우 원본에 영향이 가게된다.
  - 함수 parameter passing 도 마찬가지로, array 를 넘기면 원본 변화가 값복사여서 문제없지만,
 slice 를 넘기게되면 레퍼런스타입이라 원본의 변화가 생길수 있다.

### 슬라이스 복사하기
  - copy( DST, SRC )
  - DST 의 크기만큼만 복사된다. (= SRC가 더 큰경우 짤림)
  > 이전에 assign(=) 과 copy 의 차이는 무엇일까?

func main() { originSlice := []int{10, 11, 12} destSlice := []int{1, 2, 3, 4, 5} fmt.Println(originSlice) fmt.Println(destSlice)

// destSlice = originSlice  //-> originSlice 변화가 온다
copy(destSlice, originSlice)//-> originSlice 변화가 없다.

fmt.Println(destSlice)
destSlice[0] = 100  // destSlice 변화

fmt.Println(originSlice) // assign 과 copy 에 따라 다른결과.

}

### 슬라이스와 용량
  - 동적배열을 위해 길이와 용량을 구분하고, Go Runtime 은 정해진 알고리즘에 의해 슬라이승의 용량을 늘린다.
 > 어떤 알고리즘인가??
 [copy / append complexity](https://stackoverflow.com/questions/15702419/append-complexity) 관련글을 찾게됐고, 여기안에서 여러방식의 re-allocacte 에 대한 구현이 있다.

### 부분 슬라이스 만들기 (== Reslicing)
  - SLICE_NAME[ START_INDEX **:** END_INDEX _[: CAPACITY]_ ] 

fmt.Println("foobar"[1:3]) // "oo" numbers := [5]int{1, 2, 3, 4, 5} fmt.Println(numbers[1:3]) // [2, 3]


  - END_INDEX <= len(slice)
  - 부분슬라이스 값은 역시 reference 이기때문에, 값변경이 생길수 있다.
s := []int{1,2,3}
s = s[0:len(s)+1]
fmt.Println(s) // out of range ERROR
  - 리슬라이스 문제때문에, 내장함수(built in function) append 가 존재한다.

- 참고자료 : 더 알아야할것,
https://blog.golang.org/slices
- Passing slices to functions
- 사이즈 늘리는법 : https://blog.golang.org/go-slices-usage-and-internals
- 슬라이스 Trick : https://github.com/golang/go/wiki/SliceTricks 
  - cut, delete..등등
![2018-11-27 9 30 52](https://user-images.githubusercontent.com/9497634/49081950-bc665880-f28b-11e8-85f6-cf61174ad5ef.png)

# 맵 사용
var MAP_NAME **map**[KEY_TYPE] VALUE_TYPE  //선언
var MAP_NAME = **make**(**map**[KEY_TYPE] VALUE_TYPE)
MAP_NAME := **make**(**map**[KEY_TYPE] VALUE_TYPE)

- 맵에 데이터 저장하고 조회(key,value), (value, has) / 순회( range)

commits := map[string]int{ "jamjomja": 3711, "junhong": 2138, "dev.ik": 1908, "ghost": 912, } for name, commitCount := range commits { if(commitCount > 1000){ fmt.Println(name) } } if commitCount, ok := commits["dev.ik"] ;ok { fmt.Println(commitCount) }

- 맵에서 데이터 삭제

//map[jamjomja:3711 junhong:2138 dev.ik:1908 ghost:912] delete(commits, "ghost") fmt.Println(commits) //map[jamjomja:3711 junhong:2138 dev.ik:1908]

- 맵 in 맵

# 핵심정리

# 함수사용하기

func FUNCTION_NAME() { }

- 매개변수와 리턴값 사용하기

func functionName(params PARAM_TYPE) RETURN_TYPE { }

func functionName(params PARAM_TYPE) returnName RETURN_TYPE { returnName = operationResult return }

- 리턴값 여러개 사용하기

func functionName(a A_TYPE, b B_TYPE) ( R1_TYPE, R2_TYPE ) { return a+b, a-b }

func functionName(a A_TYPE, b B_TYPE) ( R1_TYPE, R2_TYPE ) { return a+b, a-b }

func main(){ a, _ = functionName(5, 10) // 사용하지 않는경우 }

- 가변인자 사용하기

func functionName(slice ...A_TYPE) R_TYPE { total := 0 for index , value := range slice { total += value } return total }

- 재귀호출 사용하기

func main() { fmt.Print(FibonacciRecursion(10)) // 55 }

func FibonacciRecursion(n int) int { if n <= 1 { return n } return FibonacciRecursion(n-1) + FibonacciRecursion(n-2) }

- 함수를 변수에 저장하기

func main() { var copyFib func(n int) int = FibonacciRecursion // copyFib := FibonacciRecursion fmt.Println(copyFib(10)) // 55 }

- 익명 함수 사용하기
변수 scope를 나눌수있고, 1회성으로 사용하기 편하다.

func(a int){ fmt.Println(a) }(10)

result = func(a int){ // 익명함수도 리턴을 받을수있다. return a*a }(10)



함수관련 추가자료
https://golang.org/doc/codewalk/functions/
Higher-order functions