본문 바로가기
프로그래밍/Golang

[GOLANG] 공부 (4)

by 채연2 2020. 10. 29.

● s라는 문자열 내에서 각각의 "단어"의 등장 횟수를 나타내는 맵 반환 함수
import "strings"
func WordCount(s string) map[string]int {
    wordString := make(map[string]int)
    for _,word := range strings.Fields(s) {
     wordString[word]++
    }
    return wordString
}

*스위치 (Switch)
- case의 코드 실행을 마치면 알아서 break 함 > fallthrough로 끝나는 case는 스스로 break를 하지 않음.
switch os := runtime.GOOS; os {
case "darwin":
fmt.Println("OS X.")
case "linux":
fmt.Println("Linux.")
default:
// freebsd, openbsd,
// plan9, windows...
fmt.Printf("%s.", os)
}
- 스위치에서 조건을 생략하면 switch true와 같음 > if-then-else 작성해야 할 때 사용
t := time.Now()
switch {
case t.Hour() < 12:
fmt.Println("Good morning!")
case t.Hour() < 17:
fmt.Println("Good afternoon.")
default:
fmt.Println("Good evening.")
}

*메소드 (Methods)
- 고에는 클래스가 없지만 메소드를 구조체에 붙일 수 있음.
- 메소드 리시버(method receiver)는 func 키워드와 메소드명 사이에 인자로 들어감.
type Point struct {
   X, Y, z int
}
func (p Point) printInfo() { //Point타입의 메소드
   fmt.Println(p.X)
   fmt.Println(p.Y)
   fmt.Println(p.z)
}
func main() {
   p := Point{3, 4, 5}
   p.printInfo()
}
※ 변수, 함수, 메소드
변수 : 특정 데이터를 저장하는 공간
함수 : 특정 처리의 묶음
메소드 : 객체에 연결된 함수. 즉, 특정 객체를 통해서 하려고 하는 함수들
- 메소드는 구조체뿐 아니라 아무 타입에나 붙일 수 있음 > 다른 패키지에 있는 타입이나 기본 타입들에 메소드를 붙이는 것은 불가능
type MyFloat float64
func (f MyFloat) Abs() float64 {
    if f < 0 {
        return float64(-f)
    }
    return float64(f)
}
func main() {
    f := MyFloat(-math.Sqrt2)
    fmt.Println(f.Abs())
}
- 이름이 있는 타입 또는 이름이 있는 타입의 포인터와 연결 가능.
- 포인터 리시버를 사용하는 이유
1. 메소드가 호출 될 때 마다 값이 복사되는 것(큰 구조체 타입인 경우 값이 복사되는 것은 비효율적)을 방지하기 위함.
2. 메소드에서 리시버 포인터가 가르키는 값을 수정하기 위함.

type Vertex struct {
X, Y float64
}
func (v *Vertex) Scale(f float64) {
v.X = v.X * f
v.Y = v.Y * f
}
func (v *Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
func (v Vertex) Scale2(f float64) {
v.X = v.X * f
v.Y = v.Y * f
}
func (v Vertex) Abs2() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
func main() {
//포인터 타입으로 받기 때문에 값이 변경됨
v := &Vertex{3, 4}
v.Scale(5)
fmt.Println(v, v.Abs())

//포인터가 아닌 값 타입 > 복사본에 작업을 하기 때문에 값은 변경안됨
v2 := &Vertex{3, 4}
v2.Scale2(5)
fmt.Println(v2, v2.Abs2())
}

 


*인터페이스 (Interface)
- 메소드의 집합으로 정의. 그 메소드들의 구현되어 있는 타입의 값은 모두 인터페이스 타입의 값이 될 수 있음
- struct가 interface형으로 구현될려면 interface에 정의된 메소드가 struct에 존재해야함
-  interface가 내부에 interface를 선언하면 그 선언된 interface의 메소드를 가져올 수 있음
package main

import "fmt"

type Person struct {
Name string
Age  int
}

func (this Person) hisName() {
fmt..Printf("his name is %s.\n", this.Name)
}

func (this Person) hisAge() {
fmt.Printf("his age is %d.\n", this.Age)
}

type GetName interface {
hisName()
}

type GetAge interface {
hisAge()
}

type InfoPerson interface {
GetName
GetAge
}

func main() {
var i InfoPerson
i = Person{"Kukaro", 27}
i.hisName()
i.hisAge()
}
- 암시적 인터페이스 : 인터페이스를 정의한 패키지로부터 구현 패키지를 분리해줌. 의존성 없음 > 상세하게 인터페이스를 정의하게 독려함
package main

import (
"fmt"
"os"
)

type Reader interface {
Read(b []byte) (n int, err error)
}

type Writer interface {
Write(b []byte) (n int, err error)
}

type ReadWriter interface {
Reader
Writer
}

func main() {
var w Writer

// os.Stdout implements Writer
w = os.Stdout

fmt.Fprintf(w, "hello, writer\n")
}

 

*에러 (error)
- fmt 패키지의 다양한 출력 루틴들은 error의 출력을 요청받았을 때 자동으로 이 메소드를 호출
type error interface {
Error() string
}
- 예제
type MyError struct {
    When time.Time
    What string
}

func (e *MyError) Error() string {
    return fmt.Sprintf("at %v, %s",
        e.When, e.What)
}

func run() error {
    return &MyError{
        time.Now(),
        "it didn't work",
    }
}

 

func main() {
    if err := run(); err != nil {
        fmt.Println(err)
    }
}

 

320x100

'프로그래밍 > Golang' 카테고리의 다른 글

[GOLANG] 공부 (3)  (0) 2020.10.29
[GOLANG] 공부 (2)  (0) 2020.10.29
[GOLANG] 공부 (1)  (0) 2020.10.29

댓글