yehey's 공부 노트 \n ο(=•ω<=)ρ⌒☆

[golang] 기본 문법 및 함수 본문

개발/Golang

[golang] 기본 문법 및 함수

yehey 2023. 11. 19. 23:16

변수&상수

var i, j, k int = 1, 2, 3
func main(){
        i:=1
        j:=2
}

기본적으로 변수,상수를 나타내는 키워드(var/const) 변수/상수 명 type 이렇게 3가지를 명시하는게 원칙

그치만 첨에 초기화할 때 얘도 파이썬처럼 인식하긴 함

const는 웬만하면 타입생략하고 사용할 수 있음, 초기화 필요

const (
    Visa = "Visa"
    Master = "MasterCard"
    Amex = "American Express"
)

const (
    Apple = iota // 0
    Grape        // 1
    Orange       // 2
)
//Apple=0, Grape=1, Orange=2
//status 표현할 때 좋을 것 같음

const는 여러개로 묶어서 저장할 수 있음

Data type

종류: http://golang.site/go/article/5-Go-데이타-타입

Pointer

go 에도 포인터가 잇다는 점… C와 사용법 같음

switch case

expression 어쩌고.. .그치만 필요할 때 찾아봐도 괜찮을 것 같음

http://golang.site/go/article/7-Go-조건문

가변인자 함수

func main() {   
    say("This", "is", "a", "book")
    say("Hi")
}

func say(msg ...string) {
    for _, s := range msg {
        println(s)
    }
}

고정된 수의 파라미터가 아니라 다양한 숫자의 파라미터를 전달하고자 할 때 가변 파라미터 사용

(msg는 array로 들어가나?)

함수 return

일반적으로 함수의 return 값을 써줘야 함, void일 경우에만 생략 가능

func sum(nums ...int) (count int, total int) {
    for _, n := range nums {
        total += n
    }
    count = len(nums)
    return
}

리턴으로 사용할 값을 함수 정의에서 미리 선언하고 해당 값은 일반적인 변수처럼 사용할 수 잇음

return 만 해도 go 함수에서 count,total 변수를 찾아서 해당 값을 반환하도록 되어있음

익명함수

func main() {
    sum := func(n ...int) int { //익명함수 정의
        s := 0
        for _, i := range n {
            s += i
        }
        return s
    }

    result := sum(1, 2, 3, 4, 5) //익명함수 호출
    println(result)
}

익명함수는 저렇게..만들어요… 어렵네,, 그치만 해본다

func main() {
    //변수 add 에 익명함수 할당
    add := func(i int, j int) int {
        return i + j
    }

    // add 함수 전달
    r1 := calc(add, 10, 20)
    println(r1)

    // 직접 첫번째 파라미터에 익명함수를 정의함
    r2 := calc(func(x int, y int) int { return x - y }, 10, 20)
    println(r2)

}

func calc(f func(int, int) int, a int, b int) int {
    result := f(a, b)
    return result
}

클로저 (closure)

closure는 함수 바깥에 있는 변수를 참조하는 함수값을 말함

그리고 Go 언어에서 함수는 일급함수로서 다른 함수로부터 리턴되는 리턴값으로 사용될 수 있다.

func nextValue() func() int {
    i := 0
    return func() int { 
        i++
        return i
    }
}

func main() {
    next := nextValue()

    println(next())  // 1
    println(next())  // 2
    println(next())  // 3

    anotherNext := nextValue()
    println(anotherNext()) // 1 다시 시작
    println(anotherNext()) // 2
}

defer

func main() {
    f, err := os.Open("1.txt")
    if err != nil {
        panic(err)
    }

    // main 마지막에는 항상 파일 close 실행하도록 defer 추가
    defer f.Close()

    // 파일 읽기
    bytes := make([]byte, 1024)
    f.Read(bytes)
    println(len(bytes))
}

defer은 특정 문장 혹은 함수를 defer을 호출하는 함수가 리턴하기 직정네 실행하게 하는 명령어이다.

기존에 알고있던 finally 처럼 사용

panic

func main() {
    // 잘못된 파일명을 넣음
    openFile("Invalid.txt")

    // openFile() 안에서 panic이 실행되면
    // 아래 println 문장은 실행 안됨
    println("Done") 
}

func openFile(fn string) {
    f, err := os.Open(fn)
    if err != nil {
        panic(err) //panic 발생하면 함수 멈춤
    }

    defer f.Close() //defer 실행, file close, 호출한 main으로 panic이 올라감
}

panic은 현재 함수를 즉시 멈추고 현재 함수의 defer 함수들을 모두 실행한 후 즉시 리턴한다. (긴급 종료같은 느낌) panic 모드 실행 방식은 상위 함수에도 똑같이 적용되며 콜스택을 타고 올라가며 적용된다.

마지막에는 프로그램이 에러를 내고 종료하게된다.

recover

func main() {
    // 잘못된 파일명을 넣음
    openFile("Invalid.txt")

    // recover에 의해
    // 이 문장 실행됨
    println("Done") 
}

func openFile(fn string) {
    // defer 함수. panic 호출시 실행됨
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("OPEN ERROR", r)
        }
    }()

    f, err := os.Open(fn)
    if err != nil {
        panic(err)
    }

    defer f.Close()
}

panic 함수에 의한 panic 상태를 정상으로 되돌리는 함수

panic 상태를 제거하고 정상상태로 실행하게 된다.

배열

var a [3]int // 선언 

//선언과 동시에 초기화
var a1 = [3]int{1, 2, 3} 
var a3 = [...]int{1, 2, 3} //배열크기 자동으로 

슬라이스 (slice)

배열에서 배열 크기를 지정해주지 않으면 slice가 된다.

var a []int //슬라이스 선언
a =[]int{1,2,3} //슬라이스에 값 지정 

make로 슬라이스를 생성할 수 있음, 이때는 슬라이스 길이와 용량을 임의로 정할 수 있음

func main(){
        s := make([]int, 5, 10)
    println(len(s), cap(s)) // len 5, cap 10
}

그 외의 슬라이스 관련 함수 :http://golang.site/go/article/13-Go-컬렉션---Slice

Map

var idMap map[int]string //선언

idMap = make(map[int]string) // make로 선언

구조체 struct

type person struct {
    name string
    age  int
}
//객체 생성 방법
var p1 person 
p1 = person{"Bob", 20}
p2 := person{name: "Sean", age: 50}
p3 := new(person)
p3.name = "Lee"

//생성자
type dict struct {
    data map[int]string
}

//생성자 함수 정의
func newDict() *dict {
    d := dict{}
    d.data = map[int]string{}
    return &d //포인터 전달
}

func main() {
    dic := newDict() // 생성자 호출
    dic.data[1] = "A"
}

메서드

go 메서드는 함수 정의에서 func와 함수 명 사이에 해당 함수가 어떤 struct를 위한 메서드인지를 표시할 수 있다.

//Rect - struct 정의
type Rect struct {
    width, height int
}

//Rect의 area() 메소드, value Receiver
func (r Rect) area() int {
    return r.width * r.height   
}

// 포인터 Receiver
func (r *Rect) area2() int {
    r.width++
    return r.width * r.height
}

func main() {
    rect := Rect{10, 20}
    area := rect.area() //메서드 호출
    println(rect.width,area) //10, 200
        area := rect.area2() //메서드 호출
    println(rect.width, area) // 11 220 출력
}

포인터 receiver로 메서드를 만들면, 메서드 내 r.width++ 필드 변경분이 main() 함수에서도 반영된다.

인터페이스

http://golang.site/go/article/18-Go-인터페이스

https://hwan-shell.tistory.com/344?category=895832

Go Error 처리

go 는 내장 타입으로 error 라는 interface를 갖는다.

type error interface{
        Error() string
}

해당 인터페이스를 구현하는 커스텀 에러 타입을 만들 수도 있다.

go 에서 보통 return 값에 error를 넣어준다. 그러면 error가 nil인지 여부에 따라서 에러가 발생했는지 여부를 알 수 있다.

func main() {
    f, err := os.Open("C:\\temp\\1.txt")
    if err != nil {
        log.Fatal(err.Error())
    }
    println(f.Name())
}

switch case 문으로 error 처리를 할 수도 있다.

_, err := otherFunc()
switch err.(type) {
default: // no error
    println("ok")
case MyError:
    log.Print("Log my error")
case error:
    log.Fatal(err.Error())
}

Go Package

golang은 go package를 통해 코드 모듈화, 재사용을 제공한다

go는 패키지를 이용해서 작은 단위의 컴포넌트를 작성하고, 이러한 작은 패키지들을 활용한 프로그램 작성을 권장한다.

main package

go 컴파일러는 main 패키지를 실행 프로그램으로 만들며 이때 main 패키지 안의 main 함수가 entry point 가 된다.

package scope

패키지 내의 함수, 구조체, 인터페이스, 메서드 등의 이름이 대문자로 시작하는 경우 public, 소문자로 시작하는 경우 non-public 으로 패키지 내부에서만 사용할 수 있다.

package init

package testlib

var pop map[string]string

func init() {   // 패키지 로드시 map 초기화
    pop = make(map[string]string)
}

init 함수가 있는 경우 별도 호출 없이 init함수가 자동으로 실행된다.

Comments