구조체(struct)
구조체는 여러 타입의 필드를 묶을 수 있는 자료형(타입)으로 다음과 같이 정의 할 수 있습니다.
type 타입명 struct{
필드명 타입
…
필드명 타입
}
필드(field): 구조체 내부에 있는 데이터
외부에 노출시키기 위한 public filed의 이름은 대문자로 시작
내부에서만 사용되는 private field의 필드명은 소문자로 시작
import "fmt"
type Student struct {
Name string
Class int
No int
}
func main() {
var s Student
s.Name = "yj"
s.Class = 1
s.No = 1
fmt.Println(s)
fmt.Printf("%v\n", s)
fmt.Printf("Name: %s, Class: %d, No: %d", s.Name, s.Class, s.No)
{yj 1 1}
{yj 1 1}
Name: yj, Class: 1, No: 1
위 구조체의 타입은 Stduent이며 변수 s의 타입입니다. 이 구조체의 경우 3개의 필드로 구성되므로 변수 s는 3개의 데이터를 가집니다. 변수 s에 각 필드의 호출은 연산자 .로 이루어집니다.
다음과 같이 구조체 변수의 각 필드를 초기화하지 않을 경우 기본값이 할당됩니다. 문자열의 기본값은 공백, 정수는 0, 부울은 false 입니다.
func main() {
var s Student
fmt.Println(s)
fmt.Printf("%v\n", s)
fmt.Printf("Name: %s, Class: %d, No: %d", s.Name, s.Class, s.No)
}
{ 0 0}
{ 0 0}
Name: , Class: 0, No: 0
위 s와 같이 초기화 대신 다음과 같이 실행할 수 있습니다.
func main() {
var a Student = Student{"chul", 2, 4}
var b Student = Student{Name: "gildong", Class: 3, No: 12}
fmt.Println(a)
fmt.Println(b)
}
{chul 2 4}
{gildong 3 12}
구조체는 다른 구조체를 포함할 수 있습니다. 이러한 구조체를 중첩된 구조체(nested struct)라고 합니다.
type Classinfo struct {
Class int
No int
}
type Student struct {
Name string
Class Classinfo
}
func main() {
var s Student = Student{
Class: Classinfo{Class: 7, No: 5},
Name: "John",
}
fmt.Println(s)
}
{John {7 5}}
위 코드에서 Classinfo 구조체를 사용하는 필드명은 Class입니다. 이러한 중첩된 구조체의 경우 필드명 없이 사용할 수 있으며 그 구조체의 이름이 필드의 이름이 됩니다. 이러한 필드는 임베디드 필드(embedded field)라고 합니다.
func main() {
var s Student = Student{
Classinfo: Classinfo{Class: 7, No: 5},
Name: "John",
}
fmt.Println(s.Name)
fmt.Println(s.Class)
fmt.Println(s.No)
}
John 7 5
현 구조체내에서 중첩된 구조체의 필드명과 같은 이름을 사용할 수 있습니다. 이 경우 중첩된 구조체의 필드의 호출은 구조체이름.중첩된구조체이름.필드명 또는 구조체이름.구조체의 필드명. 중첩된 구조체의 필드명과 같이 호출합니다.
type Classinfo struct {
Class int
No int
}
type Student struct {
Name string
Classinfo
No int
}
func main() {
var s Student = Student{
Classinfo: Classinfo{Class: 7, No: 5},
Name: "John",
No: 10,
}
fmt.Println(s.Name)
fmt.Println(s.Class)
fmt.Println(s.No)
fmt.Println(s.Classinfo.No)
}
John 7 10 5
구조체의 초기화는 다음 코드와 같이 필드의 이름없이 순서에 따라 할당할 수 있습니다.
package main
import "fmt"
type Vertex struct {
X int
Y int
}
func main() {
v := Vertex{1, 2}
v.X = 4
fmt.Println(v.X)
}
4
구조체는 1개 이상의 필드로 구성되어 있으므로 각 필드의 위치는 연산자 &로 나타낼 수 있습니다. 그러나 구조체 자체의 포인터는 다음과 같이 나타냅니다. 다음 코드의 p는 v의 주소를 저장하는 구조체 포인터입니다. 구조체의 위치는 구체화되지 않으므로 단지 포인터 표시만 나타냅니다.
import "fmt"
type Vertex struct {
X int
Y int
}
func main() {
v := Vertex{1, 2}
fmt.Println(&v)
fmt.Println(&v.X)
p := &v
fmt.Println(p)
p.X = 1e9
fmt.Println(v)
fmt.Println(p)
}
&{1 2}
0xc000182040
&{1 2}
{1000000000 2}
&{1000000000 2}
struct literal은 필드값을 나열하여 새로 할당된 구조체 값을 나타냅니다. 다음과 같이 여러 방법으로 각 필드에 값을 할당할 수 있습니다.
import "fmt"
type Vertex struct {
X, Y int
}
var (
v1 = Vertex{1, 2} // 필드명의 지정없이 각 필드에 값을 할당
v2 = Vertex{X: 1} // 초기화 되지 않은 필드인 경우 기본값 할당 Y:0
v3 = Vertex{} // 기본값 할당 X:0 and Y:0
p = &Vertex{1, 2} // 구조체 포인터
)
func main() {
fmt.Println(v1, v2, v3, p)
}
{1 2} {1 0} {0 0} &{1 2}
댓글
댓글 쓰기