연습 - 구조체 사용

완료됨

필드 컬렉션을 하나의 구조로 나타내야 하는 경우가 있습니다. 예를 들어, 급여 프로그램을 작성해야 하는 경우 employee 데이터 구조를 사용해야 합니다. Go에서 구조체를 사용하여 레코드를 구성할 수 있는 여러 필드를 함께 그룹화할 수 있습니다.

Go에서 ‘구조체’는 임의 형식의 필드를 0개 이상 포함하고 이러한 필드를 단일 엔터티로 표현할 수 있는 ‘다른 데이터 형식’입니다.

이 섹션에서는 구조체가 필수적인 이유와 구조체를 사용하는 방법을 알아봅니다.

구조체 선언 및 초기화

구조체를 선언하려면 새 데이터 형식에 지정할 필드 목록 및 해당 형식과 struct 키워드를 사용해야 합니다. 예를 들어, employee 구조체를 정의하기 위해 다음 코드를 사용할 수 있습니다.

type Employee struct {
    ID        int
    FirstName string
    LastName  string
    Address   string
}

그러면 다음과 같이 일반적으로 다른 형식을 사용할 때처럼 새 형식의 변수를 선언할 수 있습니다.

var john Employee

변수의 선언과 초기화를 동시에 수행하려는 경우에는 다음과 같은 방법으로 이 작업을 수행할 수 있습니다.

employee := Employee{1001, "John", "Doe", "Doe's Street"}

구조체의 각 필드에 대한 값을 지정해야 합니다. 하지만 이 경우에는 문제가 발생할 수 있습니다. 또는 구조체에서 초기화하려는 필드를 보다 구체적으로 지정할 수 있습니다.

employee := Employee{LastName: "Doe", FirstName: "John"}

이전 문에서 각 필드에 값을 할당하는 순서는 중요하지 않습니다. 또한 다른 필드에 대한 값을 지정하지 않는 경우에는 이러한 순서가 중요하지 않습니다. Go는 필드 데이터 형식에 따라 기본값을 할당합니다.

구조체의 개별 필드에 액세스하려면 다음 예제와 같이 점 표기법(.)을 사용하여 이 작업을 수행할 수 있습니다.

employee.ID = 1001
fmt.Println(employee.FirstName)

마지막으로, 다음 코드와 같이 & 연산자를 사용하여 구조체에 대한 포인터를 생성할 수 있습니다.

package main

import "fmt"

type Employee struct {
    ID        int
    FirstName string
    LastName  string
    Address   string
}

func main() {
    employee := Employee{LastName: "Doe", FirstName: "John"}
    fmt.Println(employee)
    employeeCopy := &employee
    employeeCopy.FirstName = "David"
    fmt.Println(employee)
}

위의 코드를 실행하면 다음과 같은 출력이 표시됩니다.

{0 John Doe }
{0 David Doe }

포인터를 사용할 때 어떻게 구조체가 변경 가능한지 확인합니다.

구조체 포함

Go에서 구조체를 사용하여 구조체 내에 다른 구조체를 포함할 수 있습니다. 반복을 줄이고 공용 구조체를 다시 사용하려는 경우가 있을 수 있습니다. 예를 들어, Employee와 Contractor에 대해 다른 데이터 형식을 지정하도록 이전 코드를 리팩터링하려고 합니다. 다음 예제와 같이 공통 필드를 포함하는 Person 구조체가 있을 수 있습니다.

type Person struct {
    ID        int
    FirstName string
    LastName  string
    Address   string
}

그런 다음, EmployeeContractor와 같이 Person 형식을 포함하는 다른 형식을 선언할 수 있습니다. 다른 구조체를 포함하려면 다음 예제와 같이 새 필드를 만듭니다.

type Employee struct {
    Information Person
    ManagerID   int
}

그러나 Person 구조체의 필드를 참조하려면 다음 예제와 같이 employee 변수의 Information 필드를 포함해야 합니다.

var employee Employee
employee.Information.FirstName = "John"

이와 같이 코드를 리팩터링하는 경우 코드가 중단됩니다. 또는 다음 예제와 같이 포함하려는 구조체와 동일한 이름을 가진 새 필드를 포함할 수 있습니다.

type Employee struct {
    Person
    ManagerID int
}

데모용으로 다음 코드를 사용할 수 있습니다.

package main

import "fmt"

type Person struct {
    ID        int
    FirstName string
    LastName  string
    Address   string
}

type Employee struct {
    Person
    ManagerID int
}

type Contractor struct {
    Person
    CompanyID int
}

func main() {
    employee := Employee{
        Person: Person{
            FirstName: "John",
        },
    }
    employee.LastName = "Doe"
    fmt.Println(employee.FirstName)
}

모든 필드를 자동으로 포함하게 되므로 Person 필드를 지정하지 않고도 Employee 구조체에서 FirstName 필드에 액세스하는 방법을 알아봅니다. 그러나 구조체를 초기화하는 경우에는 값을 할당하려는 필드를 구체적으로 지정해야 합니다.

JSON을 사용하여 구조체 인코딩 및 디코딩

마지막으로, 구조체를 사용하여 JSON에서 데이터를 인코딩 및 디코딩할 수 있습니다. Go는 JSON 형식을 매우 잘 지원하며, 표준 라이브러리 패키지에 이미 포함되어 있습니다.

구조체에서 필드 이름 이름을 바꾸는 등의 작업도 수행할 수 있습니다. 예를 들어, JSON 출력에 FirstName은 표시하지 않고 단순히 name만 표시하는 경우를 피하고 빈 필드를 무시하지 않으려 한다고 가정해 보겠습니다. 다음 예제와 같이 필드 태그를 사용할 수 있습니다.

type Person struct {
    ID        int    
    FirstName string `json:"name"`
    LastName  string
    Address   string `json:"address,omitempty"`
}

그런 다음, 구조체를 JSON으로 인코딩하려면 json.Marshal 함수를 사용합니다. JSON 문자열을 데이터 구조로 디코딩하려면 json.Unmarshal 함수를 사용합니다. 모든 항목을 함께 배치하고, employee 배열을 JSON으로 인코딩하고, 출력을 새 변수로 디코딩하는 예제는 다음과 같습니다.

package main

import (
    "encoding/json"
    "fmt"
)

type Person struct {
    ID        int
    FirstName string `json:"name"`
    LastName  string
    Address   string `json:"address,omitempty"`
}

type Employee struct {
    Person
    ManagerID int
}

type Contractor struct {
    Person
    CompanyID int
}

func main() {
    employees := []Employee{
        Employee{
            Person: Person{
                LastName: "Doe", FirstName: "John",
            },
        },
        Employee{
            Person: Person{
                LastName: "Campbell", FirstName: "David",
            },
        },
    }

    data, _ := json.Marshal(employees)
    fmt.Printf("%s\n", data)

    var decoded []Employee
    json.Unmarshal(data, &decoded)
    fmt.Printf("%v", decoded)
}

위의 코드를 실행하면 다음과 같은 출력이 표시됩니다.

[{"ID":0,"name":"John","LastName":"Doe","ManagerID":0},{"ID":0,"name":"David","LastName":"Campbell","ManagerID":0}]
[{{0 John Doe } 0} {{0 David Campbell } 0}]