15.2. 프로그램언어 고(Go)에서의 구조체 필드에 접근하는 방법

프로그램언어 고(Go)의 구조체에 접근하기 위한 선택자 사용

구조체에 접근하기 위한 선택자로 Go언어에서는 dot(.)을 사용합니다. 예를 들어 다음과 같은 구조체가 정의되어 있다고 가정했을 때,

type person struct {
    name string
    age  int
}

p := person{
    name: "홍길동",
    age: 30, 
}

이 구조체의 멤버에 접근하려면 다음과 같이 dot를 사용합니다.

fmt.Println(p.name) // "홍길동"
fmt.Println(p.age) // 30

dot 뒤에 접근하려는 멤버의 이름을 적으면 그 멤버에 접근할 수 있습니다. 위 예제의 경우 p라는 person 구조체의 name과 age 멤버에 접근하고 있습니다.

구조체 포인터를 사용하는 경우에도 동일한 dot 문법을 사용할 수 있습니다.

p := &person{
  name: "홍길동",
  age: 30
} 

fmt.Println((*p).name) // "홍길동" 
fmt.Println(p.age) // 30

위 예제의 경우 p는 person 구조체의 포인터입니다. 이 경우 (*p).name과 같이 구조체 포인터를 dereference 해주든지, p.age처럼 단순히 p.로 접근하든지 둘 다 가능합니다. Go언어의 특징으로 구조체 포인터도 .으로 멤버에 직접 접근할 수 있습니다.

이외에도 구조체는 중첩될 수 있고, 중첩된 구조체의 멤버에 접근할 때도 동일한 dot 문법을 사용합니다.

type person struct {
  name string
  age int
  contact contactInfo
}

type contactInfo struct {
  email string
  phone string
}

p := person{
   name: "홍길동",
   age: 30,  
   contact: contactInfo{
       email: "hong@example.com",
       phone: "010-1234-5678",
   }
}

fmt.Println(p.contact.email) // "hong@example.com"

위 예제에서 볼 수 있듯이 중첩 구조체인 contactInfo 구조체의 email 멤버에도 dot을 사용하여 접근할 수 있습니다.

이처럼 Go언어의 구조체에서 멤버에 접근할 땐 항상 dot을 사용하는 것이 기본 원칙입니다. dot 뒤에 접근하고자하는 멤버의 이름을 적어주면 됩니다. 중첩 구조체의 경우에도 동일하게 적용됩니다.

프로그램언어 고(Go)에서의 포인터를 이용한 구조체 필드 접근

프로그램언어 고(Go)에서의 포인터를 이용한 구조체 필드 접근에 대해 설명드리겠습니다.

고(Go)언어에서 포인터를 이용하여 구조체의 필드에 접근할 수 있습니다. 이를 통해 구조체의 필드를 직접 수정할 수 있고, 메모리 절약의 효과도 있습니다.

예를 들어 다음과 같은 구조체가 정의되어 있다고 합시다.


type person struct {
    name string
    age  int
}

이 구조체의 인스턴스를 생성하고, 포인터를 이용하여 접근한다면 다음과 같이 할 수 있습니다.


p := &person{name: "John", age: 30} 

p.name = "Anna" // 포인터를 통해 구조체 필드 접근
p.age = 25 // 구조체 age 필드 수정

fmt.Println(p.name, p.age) // Anna 25 출력

p 변수는 person 구조체의 포인터입니다.

이 p를 통해서 구조체의 name과 age 필드에 직접 접근하여 수정할 수 있습니다.

포인터를 사용하지 않고 값에 의한 복사(value copy)로 작업한다면 수정이 반영되지 않을 것입니다.

따라서 포인터를 이용하는 것이 효율적입니다.

마지막으로 p.name, p.age 처럼 구조체 포인터를 통해 필드에 접근하는 문법은 구조체 값 자체로 접근하는 것과 동일하다는 점에 유의하시기 바랍니다.

이상으로 프로그램언어 고(Go)에서의 포인터를 이용한 구조체 필드 접근에 대해 간략히 설명 드렸습니다. 잘 이해가 가시길 바랍니다.

프로그램언어 고(Go)에서의 익명 필드에 접근하는 방법

프로그램언어 고(Go)에서 익명 필드에 접근하는 방법은 구조체 내부에 정의되지 않은 필드를 사용할 때 주로 활용됩니다. 익명 필드는 실제로 존재하지 않지만 구조체를 초기화할 때 값을 제공할 수 있습니다.

일반적인 사용 예시는 다음과 같습니다.


package main

import "fmt"

type Person struct {
    Name string
    Age  int
    // 익명 필드
    string
    int
}

func main() {
    p := Person{
        Name: "홍길동",
        Age:  30,
        "서울",   // 익명 필드에 문자열 할당
        50,       // 익명 필드에 정수 할당 
    }

    // 익명 필드에 직접 접근 불가
    // fmt.Println(p.string, p.int)  

    // 리플렉션을 사용한 간접 접근
    rv := reflect.ValueOf(p)
    sf := rv.Field(2) // 익명 필드 순서대로 인덱스 사용
    fmt.Println(sf)  // 서울

    iv := rv.Field(3)
    fmt.Println(iv)  // 50
}

위 예시에서 볼 수 있듯이 익명 필드에는 직접 접근할 수 없습니다. 대신 reflect 패키지의 리플렉션 기능을 사용하여 간접적으로 접근할 수 있습니다.

reflect.Value의 Field 메서드에 익명 필드의 인덱스를 입력하면 해당 필드의 값을 얻을 수 있습니다. 익명 필드는 구조체 정의 시 순서대로 0부터 인덱스가 할당됩니다.

이러한 간접 접근 방식은 코드가 다소 복잡할 수 있으나, 필요한 경우 가변 길이의 익명 필드를 활용할 수 있다는 장점이 있습니다.

예를 들어 데이터가 가변 길이일 때, 구조체 정의 없이도 익명 필드를 사용하여 해당 데이터를 구조체에 담을 수 있습니다.

따라서 고(Go)에서는 익명 필드의 간접 접근 허용으로, 유연하고 효율적인 데이터 처리가 가능합니다.

프로그램언어 고(Go)의 구조체 필드의 가시성 관리

프로그램언어 고(Go)에서 구조체 필드의 가시성을 관리하는 방법은 대문자로 시작하는 필드는 public으로, 소문자로 시작하는 필드는 private으로 처리됩니다.

구조체 필드의 가시성 관리에 대한 예제 코드는 다음과 같습니다.


package main

import "fmt"

type User struct {
  Name string // public 필드
  age  int    // private 필드
}

func main() {
  u := User{"홍길동", 30}

  // Name 필드는 public이기 때문에 직접 접근 가능
  fmt.Println(u.Name) 

  // age 필드는 소문자로 시작하여 private이기 때문에 직접 접근 불가능
  // fmt.Println(u.age)   
}

이 예제에서 User 구조체는 public인 Name 필드와 private인 age 필드를 가지고 있습니다.

Name 필드는 대문자로 시작하여 public으로 선언된 필드이기 때문에 main() 함수에서 직접 접근이 가능합니다.

하지만 age 필드는 소문자로 시작하여 private으로 선언된 필드이기 때문에 main() 함수에서 직접 접근이 불가능합니다.

이처럼 고(Go)에서는 구조체 필드명의 가시성을 대소문자를 통해 쉽게 제어할 수 있는 장점이 있습니다.

프로그램언어 고(Go)에서의 읽기 전용 구조체 필드 생성 및 접근

프로그램언어 고(Go)에서 구조체 필드를 읽기 전용으로 선언하려면 struct 태그에 readonly 옵션을 사용합니다. 이를 통해 해당 필드를 읽기 전용으로 만들 수 있습니다.

type User struct {
    ID        int     `readonly` 
    FirstName string
    LastName  string
}

위의 예제코드에서 User 구조체의 ID 필드는 읽기 전용으로 선언됩니다. 읽기 전용 필드는 생성자를 통해서만 값을 할당할 수 있습니다.

u := User{
    ID:        1,
    FirstName: "John", 
    LastName:  "Doe",
}

위처럼 생성자를 사용하여 값을 할당할 수 있습니다. 하지만 일반 메서드를 통해서는 읽기 전용 필드에 값을 변경할 수 없습니다.

func editUser(u *User) {
    u.ID = 2 // 컴파일 에러 발생!
}

읽기 전용 필드에 접근하여 값을 읽는 것은 가능합니다.

id := u.ID // okay

이처럼 구조체 태그의 readonly 옵션을 사용하면 읽기 전용 필드를 쉽게 생성할 수 있습니다. 이는 실수로 값이 변경되는 것을 방지하기 위해 유용하게 사용할 수 있습니다.

Leave a Comment