Golang_정리하기_4

[Go tutorial] Go 정리하기 - 4

Go-tour 참조

구름edu 참조

  • 스위치 (switch)

    • case의 라벨과 일치하는경우를 찾아 실행

    • 어느것에도 맞지않다면 default문으로 실행 가능

    • break를 따로 입력하지 않아도 해당되는 case문만 실행된다.

    • 스위치의 각 조건은 위에서 아래로 평가한다. 참인 case를 찾으면 평가를 마침.

    • switch 전달 인자

      • 태그

      • 표현식

      • 전달되는 인자 없이 case에 표현식 사용 가능

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        func main() {
        var a, b int

        fmt.Print("정수 a와 b를 입력하시오:")
        fmt.Scanln(&a, &b)

        switch {
        case a > b:
        fmt.Println("a가 b보다 큽니다.")
        case a < b:
        fmt.Println("a가 b보다 작습니다.")
        case a == b:
        fmt.Println("a와 b가 같습니다.")
        default:
        fmt.Println("모르겠어요.")
        }
        }
  • 메소드와 인터페이스

    • 메소드란 특정 속성들(구조체)을 이용해 기능을 수행하기 위해 만들어진 함수이다.

    • 선언

      • “func (매개변수이름 구조체이름) 메소드이름() 반환형 {}” 형식으로 선언
    • 매개변수 이름은 메소드 내에서 매개변수처럼 사용

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      type Vertex struct {
      X, Y float64
      }

      func (v *Vertex) Abs() float64 {
      return math.Sqrt(v.X*v.X + v.Y*v.Y)
      }

      func main() {
      v := &Vertex{3, 4}
      fmt.Println(v.Abs()) ### print : 5
      }
    • 위의 예에서는 메소드에 구조체를 붙였다.

    • 뿐만 아니라 메소드에는 아무 타입이나 붙일 수 있다.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      type MyFloats float64

      func (f MyFloats) Abs() float64 {
      if f < 0 {
      return float64(-f)
      }
      return float64(f)
      }

      func main() {
      k := MyFloats(-math.Sqrt2)
      fmt.Println(k.Abs()) ### print : 1.4142135623730951
      }
    • 위의 예에서는 float타입을 메소드에 붙였다.

  • 인터페이스

    • 구조체가 변수를 묶어놓은 것이라면, 인터페이스는 메소드를 모아놓은 것이다.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      package main

      import (
      "fmt"
      "math"
      )

      type geometry interface {
      area() float64
      perimeter() float64
      }

      type Rect struct {
      width, height float64
      }

      type Circle struct {
      radius float64
      }

      func (r Rect) area() float64 {
      return r.width * r.height
      }

      func (c Circle) area() float64 {
      return math.Pi * c.radius * c.radius
      }

      func (r Rect) perimeter() float64 {
      return 2 * (r.width + r.height)
      }

      func (c Circle) perimeter() float64 { .Pi * c.radius
      }

      func main() {
      r1 := Rect{10, 20}
      c1 := Circle{10}
      r2 := Rect{12, 14}
      c2 := Circle{5}

      printMeasure(r1, c1, r2, c2)
      }

      func printMeasure(m ...geometry) {
      for _, val := range m {
      fmt.Println(val)
      fmt.Println(val.area())
      fmt.Println(val.perimeter())
      }
      }
    • 위의 예를 보면 인터페이스 안에 메소드가 들어가있다. 또한, 같은 이름의 메소드가 두개씩 있다.

    • 이름이 동일하게 선언되어도 메소드가 전달받는 구조체가 다르기 때문에 괜찮은것이다.

    • 메인함수에서 구조체를 초기화하고 for문을 통해 각 구조체를 전달받은 메소드에 대해 결과값을 출력하고 있다.

    • 빈 인터페이스

      • 인터페이스는 어떠한 타입도 담을 수 있는 dynamic type 이다.

      • 인터페이스는 매개변수로 사용할 수 있다.

      • 인터페이스는 내용을 따로 선언하지 않아도 형으로 사용할 수 있다.

      • 하나의 변수를 형이 다른 형태로 저장해 출력한다고 생각한다면, 매개변수형에 따른 2개 이상의 함수를 만들어야한다.

      • 하지만 빈 인터페이스를 사용한다면, 어떤 형도 담을 수 있기 때문에 편하게 사용이 가능하게된다.

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        package main

        import "fmt"

        func printVal(i interface{}) {
        fmt.Println(i)
        }

        func main() {
        var x interface{} //빈 인터페이스 선언

        x = 1
        printVal(x)

        x = "test"
        printVal(x)
        }
      • 위의 예에서 x의 값에따라 다르게 형을 선언하지 않고 출력하는것을 확인할 수 있다.

Golang_정리하기_3

[Go tutorial] Go 정리하기 - 3

Go-tour 참조

구름edu 참조

  • 맵(map)

    • 키와 value의 조합을 나타내기 위한것으로 파이썬의 딕셔너리를 생각하자.

    • var 맵이름 map[key자료형]value자료형 으로 선언

      • var a map[int]string :: key가 int이고 value가 string인 맵 a
    • 선언만 하고 초기화하지 않는다면 Nil map 이다.

    • 데이터 추가 or 갱신 :: 맵이름[key] = value 를 이용

    • 데이터 삭제 :: delete(맵이름,key) 를 이용

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      func main() {
      //지역번호와 지역 저장
      var m = make(map[string]string)

      m["02"] = "서울특별시"
      m["031"] = "경기도"
      m["032"] = "충청남도"
      m["053"] = "대구광역시"

      fmt.Println(m)

      //동일한 key값으로 value값을 저장하면 갱신이 된다
      m["032"] = "인천"

      fmt.Println(m)

      //m에 있는 "031"key의 value와 함께 삭제
      delete(m, "031")

      fmt.Println(m)
      }
    • key체크, value 확인

      • “맵이름[key]” 는 value와 키가 존재하는지 여부를 반환한다.

      • 존재하지 않는 키값이라면 자료형에따라 0 혹은 “” 를 반환

      • 해당 키가 존재하는지 여부에 따라 true/false 반환

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        func main() {
        m := make(map[string]int)

        m["Answer"] = 42
        fmt.Println("The value:", m["Answer"])
        ## print : The value: 42
        m["Answer"] = 48
        fmt.Println("The value:", m["Answer"])
        ## print : The value: 48
        delete(m, "Answer")
        fmt.Println("The value:", m["Answer"])
        ## print : The value: 0
        v, ok := m["Answer"]
        fmt.Println("The value:", v, "Present?", ok)
        ## print : The value: 0 Present? false
        }
  • 연습 : 맵 - 문제

  • 함수 클로져

    • 클로져는 함수 안에서 익명 함수를 정의해 바깥쪽 함수에서 선언한 변수에도 접근할 수 있는 함수를 뜻한다.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      func adder() func(int) int {
      sum := 0
      return func(x int) int {
      sum += x
      return sum
      }
      }

      func main() {
      pos, neg := adder(), adder()
      for i := 0; i < 10; i++ {
      fmt.Println(
      pos(i),
      neg(-2*i),
      )
      }
      }
    • 위의 예에서 adder() 함수는 지역 변수 sum 을 초기화하고 입력받는 x를 더해주는 익명 함수를 반환합니다.

    • for문에서 함수가 실행될때마다 지역 변수가 초기화되지않고 더해주는 익명함수만을 통해 값이 지속적으로 증가/감소 하는것을 확인할 수 있습니다.

  • 연습 : 피보나치 클로져 - 문제

Golang_정리하기_2

[Go tutorial] Go 정리하기 - 2

Go-tour 참조

구름edu 참조

  • 구조체(Structs)

    • structs는 데이터들의 조합

    • type선언으로 이름을 지정할 수 있음

    • “객체이름 := 구조체이름{저장할값}”으로 입력해 선언과 동시에 초기화할 수 있다.

    • 구조체에 속한 필드(데이터)는 dot(.)으로 접근

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      type person struct {
      name string
      age int
      contact string
      }

      func main() {
      var p1 = person{}
      fmt.Println(p1)

      p1.name = "kim"
      p1.age = 25
      p1.contact = "01000000000"
      fmt.Println(p1)

      p2 := person{"nam", 31, "01022220000"} // 필드 이름을 생력할 시 순서대로 저장함
      fmt.Println(p2)

      p3 := person{contact: "01011110000", name: "park", age: 23} // 필드 이름을 명시할 시 순서와 상관 없이 저장할 수 있음
      fmt.Println(p3)

      p3.name = "ryu" //필드에 저장된 값을 수정할 수 있음
      fmt.Println(p3)

      fmt.Println(p3.contact) //필드 값의 개별 접근도 가능함
      }
  • 포인터

    • 포인터 연산은 불가능

    • 포인터를 이용한 간접 접근은 실제 구조체에도 영향을 끼침

    • “&” 을 매개변수 앞에 붙여 pass by reference 를 통해 값이 저장된 주소에 직접 접근할 수 있음.

    • 구조체 포인터를 생성하는 방법은 두 가지가 있다.

      • ‘new(구조체이름)’ 을 사용하여 객체를 생성

      • 구조체 이름 앞에 & 붙이기

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        type Person struct {
        Name string
        }

        func main() {
        c := new(Person) // returns pointer
        c.Name = "Catherine"
        fmt.Println(c.Name) // prints: Catherine

        d := *c
        d.Name = "Daniel"
        fmt.Println(d.Name) // prints: Daniel

        i := &d
        i.Name = "Ines"
        fmt.Println(c.Name) // prints: Catherine
        fmt.Println(d.Name) // prints: Ines
        fmt.Println(i.Name) // prints: Ines
        }
  • 슬라이스(slice)

    • 슬라이스는 참조 타입이다. 따라서, 슬라이스를 복사한다는 것은 같은 주소를 참조한다는 것이다. 복사한 슬라이스의 값을 바꾸면 참조하는 슬라이스의 해당 값도 바뀌게 된다.

    • 슬라이스 선언

      • var a []int = []int{1,2,3,4} 와 같이 선언과 함께 초기화

      • make() 함수를 이용.

      • make(슬라이스 타입, 슬라이스 길이, 슬라이스 용량)

      • ex) s:=make([]int,3,3)

    • append() 함수를 통해 슬라이스에 데이터를 추가할 수 있다.

    • 슬라이스에 슬라이스를 추가하기 위해서는 슬라이스 뒤에 “…”을 입력

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      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)
      fmt.Println(sliceB)
      }
    • copy(붙여넣을 슬라이스, 복사할 슬라이스) 를 통해 한 슬라이스를 다른 슬라이스로 복사할 수 있다.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      func main() {
      c := make([]int, 0, 3) //용량이 3이고 길이가0인 정수형 슬라이스 선언
      c = append(c, 1, 2, 3, 4, 5, 6, 7)
      fmt.Println(len(c), cap(c))

      l := c[1:3] //인덱스 1요소부터 2요소까지 복사
      fmt.Println(l)

      l = c[2:] //인덱스 2요소부터 끝까지 복사
      fmt.Println(l)

      l[0] = 6

      fmt.Println(c) //슬라이스 l의 값을 바꿨는데 c의 값도 바뀜
      //값을 복사해온 것이 아니라 기존 슬라이스 주솟값을 참조
      }
    • 위의 예제를 실행해보면 slice c의 값도 l 에 의해 바뀌는것을 확인할 수 있다. 왜냐하면, 슬라이스는 배열과 다르게 슬라이스 자체가 참조하고 있는 주소값을 같이 참조하기 때문이다.

    • 슬라이스 순회(iterates)

      • 슬라이스는 for 반복문에서 range를 통해 순회할 수 있다.

      • 이때, index와 value를 순회하며 필요치 않은 값은 “_” 를 이용해 무시할 수 있다.

Golang_정리하기-1

[Go tutorial] Go 정리하기 - 1

Go-tour 참조

  • 익스포트

    • Go 에서는 첫 문자가 대문자로 시작하면 특정 패키지를 사용하는 곳에서 접근할 수 있는 exported name이 됨
  • 함수

    • Go 는 코드를 왼쪽부터 자연스럽게 읽기 위해 매개변수 타입은 변수명 뒤에 명시.

    • 두 개 이상의 매개변수가 같은 타입일 때, 같은 타입을 취하는 마지막 매개변수에만 타입을 지정할 수 있음.

      1
      2
      3
      4
      5
      x int, y int

      #를 아래와 같이도 사용 가능

      x, y int
    • 하나의 함수는 여러 개의 결과를 반환할 수 있음.

      1
      2
      3
      func swap(x, y string) (string, string) {
      return y, x
      }
  • 변수

    • var 을 통해 변수를 선언.

    • 변수 선언과 함꼐 초기화 가능, 초기화를 하는 경우 타입 생략 가능. 이 경우, 초기화하고자 하는 값에 따라 타입이 결정됨.

      1
      var a, b, c int = 1, 2, 3
    • 함수 내에서 := 을 사용하면 var와 명시적인 타입을 생략할 수 있음.

  • 상수

    • const 키워드와 함께 변수처럼 선언.

    • 상수는 문자, 문자열, boolean, 숫자 타입 중의 하나가 될 수 있음

    • 숫자형 상수는 정밀한 값을 표현할 수 있음. Go-tour 사이트에서 제공하는 예제를 이해하기 위해서는 Go의 << 와 >> 연산자의 이해가 필요하다.

    • <<, >> 연산자에 대해

      • << 와 >> 연산자는 비트 이동 연산자로 Left shift, Right shift 라고 함.
      • Left shift 는 현재 값의 비트를 주어진 값만큼 왼쪽으로 Right shift는 현재 값의 비트를 주어진 값만큼 오른쪽으로 옮깁니다.
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        const (
        a = 1
        b = a << 1
        )

        func main() {
        fmt.Println(a) ### 1 출력
        fmt.Printf("%08b\n", a) ### 00000001 출력
        fmt.Println(b) ### 2 출력
        fmt.Printf("%08b", b) ### 00000010 출력
        }
  • 반복문 for

    • Go 에는 반복문으로 for 하나만 존재.

    • 조건문만 표현해서 루프를 표현 가능.

      1
      2
      3
      4
      5
      6
      7
      func main() {
      sum := 1
      for sum < 1000 {
      sum += sum
      }
      fmt.Println(sum)
      }
    • 위와 같이 표현하면 while을 사용하듯 for을 사용할 수 있다.

    • 조건문을 생략하는것으로 무한 루프를 만들 수 있다.

      1
      2
      3
      4
      func main() {
      for {
      }
      }
  • 조건문 if

    • 반복문과 마찬가지로 실행문을 위한 { } 만 필요.

    • for 처럼 조건문 앞에 문장을 실행할 수 있음.

      1
      2
      3
      4
      5
      6
      func pow(x, n, lim float64) float64 {
      if v := math.Pow(x, n); v < lim {
      return v
      }
      return lim
      }
    • 위의 예를 보면, v < lim 을 통한 조건문 앞에 v := math.Pow(x,n) 을 실행했다.

    • 이렇게 선언된 변수(위에서는 v)는 if 안쪽 범위에서만(else 블럭 안에서도 가능) 사용할 수 있다.

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×