로즈마리

글 작성자: daily_zi

_Struct (구조체)

Go에서 struct는 Custom Data Type을 표현하는데 사용되는데, Go의 struct는 필드들의 집합체이며 필드들의 컨테이너이다. Go에서 struct는 필드 데이타만을 가지며, (행위를 표현하는) 메서드를 갖지 않는다.

Go 언어는 객체지향 프로그래밍(Object Oriented Programming, OOP)을 고유의 방식으로 지원하지만, 전통적인 OOP 언어가 가지는 클래스, 객체, 상속 개념이 없다.

전통적인 OOP의 클래스(class)는 Go 언어에서 Custom 타입을 정의하는 struct로 표현되는데, 전통적인 OOP의 클래스가 필드와 메서드를 함께 갖는 것(Java에서의 getter, setter)과 달리 Go 언어의 struct는 필드만을 가지며, 메서드는 별도로 분리하여 정의한다.


_Struct(구조체) 선언

  • type 구조체명 struct { }

struct를 정의하기 위해서는 Custom Type을 정의하는데 사용하는 type 문을 사용한다.

예를 들어 width과 height 필드를 갖는 rectangle 이라는 struct를 정의하기 위해서는 아래와 같은 type문을 사용할 수 있다. 만약 이 rectangle 구조체를 패키지 외부에서 사용할 수 있게 하려면 struct명을 Rectangle으로 변경하면 된다.

package main
 
import "fmt"
 
// struct 구조체 정의
type rectangle struct {
	width  int
	height int
}
 
func main() {
    // rectangle 객체 생성
    r := rectangle{}
     
    // 필드값 설정
    r.width  = 100
    r.height = 120
     
    fmt.Println(r)
}

 


_Struct(구조체) 객체 생성

  • var 변수명 구조체_타입

선언된 struct 타입으로부터 객체를 생성하는 방법은 몇 가지 방법들이 있다. 위의 예제처럼 rectangle{} 를 사용하여 빈 rectangle 객체를 먼저 할당하고, 나중에 그 필드값을 채워넣는 방법이 있다. struct 필드를 접근하기 위해서는 .(r.width, r.height)을 사용한다.

 

struct 객체를 생성할 때, 초기값을 함께 할당하는 방법도 있다. struct 필드값을 순서적으로 { } 괄호안에 넣을 수 있으며, 두번째 예처럼 순서에 상관없이 필드명을 지정하고(named field) 그 값을 넣을 수 도 있다. 특히 필드명을 지정하는 경우, 만약 일부 필드가 생략될 경우 생략된 필드들은 Zero value (정수인 경우 0, float인 경우 0.0, string인 경우 "", 포인터인 경우 nil 등)를 갖는다.

var r1 rectangle 
r1  = rectangle{200, 120}
r2 := rectangle{width: 500, height: 150}

또 다른 객체 생성 방법으로 Go 내장함수 new()를 쓸 수 있다.

new()를 사용하면 모든 필드를 Zero value(정수인 경우 0, float인 경우 0.0, string인 경우 "", 포인터인 경우 nil 등)로 초기화하고 rectangle 객체의 포인터(*rectangle)를 리턴한다. 객체 포인터인 경우에도 필드 접근 시 .을 사용하는데, 이 때 포인터는 자동으로 Dereference 된다.

r := new(rectangle)
r.width = 250  // r가 포인터라도 . 을 사용한다

Go에서 struct는 기본적으로 mutable(변덕스러운) 개체로서 필드값이 변화할 경우 (별도로 새 개체를 만들지 않고) 해당 개체 메모리에서 직접 변경된다. 하지만, struct 개체를 다른 함수의 파라미터로 넘긴다면, Pass by Value에 따라 객체를 복사해서 전달하게 된다. 그래서 만약 Pass by Reference로 struct를 전달하고자 한다면, struct의 포인터를 전달해야 한다.


_Struct 생성자(constructor) 함수

구조체(struct)의 필드는 사용 전에 초기화되어야 하는 경우가 있다. 예를 들어, struct 의 필드가 map 타입인 경우 map을 사전에 미리 초기화해 놓으면, 외부 struct 사용자가 매번 map을 초기화 해야 된다는 것을 기억할 필요가 없다. 이러한 목적을 위해 생성자 함수를 사용할 수 있다. 생성자 함수는 struct를 리턴하는 함수로서 그 함수 본문에서 필요한 필드를 초기화한다.

아래 예제에서 생성자 함수 newDict()는 dict라는 struct의 map 필드를 초기화한 후 그 struct 포인터를 리턴하고 있다. 이어 main() 함수에서 struct 개체를 만들 때 dict 를 직접 생성하지 않고 대신 newDict() 함수를 호출하여 이미 초기화된 data 맵 필드를 사용하고 있다.

 

package main
 
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' 카테고리의 다른 글

Go 언어 입문_Method(메소드)  (0) 2019.09.09
Go 언어 입문_함수*  (0) 2019.09.06
Go 언어 입문_변수  (0) 2019.09.02
Go 언어 입문  (1) 2019.09.02
jteeuwen/go-bindata  (0) 2019.06.24