Struct의 멤버로 Struct를 사용하는게 가능하다
package main
import "fmt"
type Student struct {
Name string
Class int
No int
Score float64
}
type VIPStudent struct {
stud Student
isVIP bool
}
func main() {
var student VIPStudent
student.stud.Name = "홍길동"
student.isVIP = true
fmt.Println("이름 : ", student.stud.Name)
fmt.Println("VIP : ", student.isVIP)
}
메모리 정렬을 통해 효율적으로 저장공간을 사용할 수 있게 해야한다
// Not Good, 56byte
type Padding struct{
A int8 // 8byte (padding)
B int // 8byte
C float64 // 8byte
D uint16 // 8byte (padding)
E int // 8byte
F float32 // 8byte (padding)
G int8 // 8byte
}
// Good, 32byte
type Padding struct{
A int8 // 1byte
G int8 // 1byte
D uint16 // 2byte
F float32 // 4byte
B int // 8byte
C float64 // 8byte
E int // 8byte
}
생성과 동시에 바로 사용할 수밖에 없는 익명 구조체
func main() {
p1 := struct {
first string
last string
}{first: "James", last: "Bond"}
fmt.Println(p1)
}
Marshaling
package main
import (
"encoding/json"
"fmt"
)
type Employee struct {
Name string `json:"empname"`
Number int `json:"empid"` // number와 같이 소문자로 작성 시 json/encoding에서 파싱되지 않아 무시 됨
}
func main() {
employee_1 := &Employee{Name: "Dixya Lhyaho", Number: 10}
// Marshal
e, err := json.Marshal(employee_1) // MarshalIndent 사용 시 들여쓰기가 적용됨
if err != nil {
fmt.Println(err)
return
}
fmt.Println(e) // [123 34 101 109 112 110 97 109 101 34 58 34 68 105 120 121 97 32 76 104 121 97 104 111 34 44 34 101 109 112 105 100 34 58 49 48 125]
fmt.Println(string(e)) // {"empname":"Dixya Lhyaho","empid":10}
// Unmarshal
var emp Employee
err2 := json.Unmarshal(e, &emp)
if err2 != nil {
fmt.Println(err2)
return
}
fmt.Println(emp.Name) // 10
fmt.Println(emp.Number) // Dixya Lhyaho
}
참고 사항. Unmarshal vs Decode
json.Umarshal
decoder.Decode
- 변수 대입과 함수 인수 전달은 항상 값을 복사하기 때문에 메모리 비효율과 성능 문제를 발생 시킴
- 포인터는 이 부분을 효과적으로 해결함
package main
import "fmt"
type Data struct {
value int
data [200]int
}
func ChangeData(arg *Data) {
arg.value = 999
arg.data[100] = 999
}
func main() {
var data Data
// 포인터로 전달하지 않으면 값이 변경되지 않음
ChangeData(&data)
fmt.Printf("value = %d\n", data.value)
fmt.Printf("data[100] = %d\n", data.data[100])
}
구조체 변수를 생성하지 않고 곧바로 포인터 변수에 구조체 생성하여 초깃값 대입 가능
// 구조체 변수 생성 및 초깃값 대입
var data Data
var p *Data = &data
// 구조체 생성과 동시에 초깃값 대입
var p *Data = &Data{} // 방법 1
var p = new(Data) // 방법 2
포인터를 복사하면 인스턴스가 생기는 것이 아님
// 인스턴스가 추가로 생성되는 것이 아님 (인스턴스 1개, 포인터가 동일하게 가르킴)
var p1 *Data = &Data{}
var p2 *Data = p1
var p3 *Data = p2
// 값만 동일하고 각각 개별적인 인스턴스가 생김 (인스턴스 3개)
var data1 Data
var data2 Data = data1
var data3 Data = data1
함수 외부로 공개되는 인스턴스의 경우 함수가 종료되어도 살아있음
package main
import "fmt"
type User struct{
Name string
Age int
}
func NewUse(name string, age int) *User{
// 함수 내부에서 선언이 되었지만, 외부에서도 접근이 가능함
var u = User{name,age}
return &u
}
func main(){
userPointer := NewUse("AAA",23)
fmt.Println(userPointer)
}