이동 언어는 상속과 기타 객체 지향 개념의 "클래스"를 지원하지 않습니다 "클래스"의 개념이 없습니다. 의 인터페이스 언어와 결합 이동 포함 된 구조를 통해 확장 성 및 유연성이보다 높은 객체 지향.
유형 별칭 및 사용자 정의 유형
사용자 정의 유형
이러한 이동 언어와 같은 몇 가지 기본 데이터 유형이 있습니다 string
, 整型
, 浮点型
, 布尔
및 기타 데이터 유형, 당신은 이동의 언어 사용할 수있는 type
사용자 정의 유형을 정의하는 키워드를.
사용자 정의 유형은 새로운 유형을 정의하는 것입니다. 우리는 내장 된 기본 유형도 구조체로 정의 할 수 있습니다에 따라 정의 할 수 있습니다. 예를 들면 :
//将MyInt定义为int类型
type MyInt int
하여 Type
키워드의 정의 MyInt
가있는 새로운 유형의 int
속성을.
유형 별칭
유형 별칭은 Go1.9
새 버전의 기능이 추가.
별명 조항을 입력 TypeAlias는 본질적으로 별칭을 입력 TypeAlias 및 유형은 동일한 유형입니다. 아이처럼 아이의 별명, 애완 동물 이름, 학교, 영어 교사와 그에게 영어 이름을 부여하기위한 과학적인 이름을 가지고 있지만 이들 이름은 모두 개인적으로 그에게 참조하십시오.
type TypeAlias = Type
우리는 전에 본 적이 rune
, 그리고 byte
다음과 같이가 정의 된 유형의 별칭입니다 :
type byte = uint8
type rune = int32
타입 정의 및 종류 별명 차이점
유형 별칭 유형 정의가 등호의 표면 사이의 유일한 차이점입니다, 우리는 코드를 따라 그들 사이의 차이를 이해한다.
//类型定义
type NewInt int
//类型别名
type MyInt = int
func main() {
var a NewInt
var b MyInt
fmt.Printf("type of a:%T\n", a) //type of a:main.NewInt
fmt.Printf("type of b:%T\n", b) //type of b:int
}
결과는 형태가 것을 보여 main.NewInt
주 패키지의 정의를 보여주는 NewInt
타입. B 형이다 int
. MyInt
이 컴파일되지 않을 때 코드를 입력에만 존재합니다 MyInt
유형.
구조
데이터 유형은 몇 가지 기본 속성의 언어로 표현 될 수있는 기본 이동,하지만 우리는 사물의 재산의 전부 또는 일부를 표현하고자 할 때, 다음 하나의 기본 데이터 유형 분명히이 시간이 수요를 충족 할 수없는 언어가 제공 이동 사용자 정의 데이터 형식의 종류,이 구조, 영어 이름이라는 기본 데이터 유형, 데이터 유형의 복수를 캡슐화 할 수 있습니다 struct
. 즉, 우리는 수 struct
의 자신의 유형을 정의합니다.
언어를 통해 이동 struct
객체 지향 구현.
구조의 정의
사용 type
하고 struct
다음과 같은 구조를 정의하는 키워드, 특정 코드의 형식은 다음과 같습니다
type 类型名 struct {
字段名 字段类型
字段名 字段类型
…
}
장소 :
- 유형 이름 : 사용자 정의 구조의 이름을 식별, 같은 패키지에서 반복 할 수 없습니다.
- 필드 이름 : 구조 필드 이름을 나타냅니다. 구조체 필드 이름은 고유해야합니다.
- 필드 형식 : 필드의 특정 구조의 유형을 나타냅니다.
예를 들어, 정의는 Person
다음과 같이, (인간) 구조체를 :
type person struct {
name string
city string
age int8
}
필드의 동일한 유형은, 한 줄에 쓸 수 있습니다
type person1 struct {
name, city string
age int8
}
그래서 우리는이 person
가있다, 사용자 정의 유형을 name
, city
, age
세 개의 필드는 각각 도시와 연령의 이름을 지정합니다. 우리는이 사용 person
구조를 쉽게 표현하고 프로그램의 개인 정보를 저장할 수 있습니다.
기본 데이터 형식을 설명하는 데 사용되는 언어로 내장하는 값이며, 구조 값의 세트를 설명하는 데 사용된다. 예를 들어, 사람은 본질적으로 데이터의 고분자 타입, 이름, 나이, 거주 도시 등이있다
구조로서는
구조가 인스턴스화 될 때에 만, 실제로 메모리를 할당합니다. 즉, 필드 구조를 사용하기 위해 인스턴스화해야합니다.
자체, 우리는 선언과 같은 내장 유형을 사용할 수 있습니다 구조의 유형 var
구조 유형을 선언하는 키워드.
var 结构体实例 结构体类型
기본 인스턴스
예를 들면 :
type person struct {
name string
city string
age int8
}
func main() {
var p1 person
p1.name = "沙河娜扎"
p1.city = "北京"
p1.age = 18
fmt.Printf("p1=%v\n", p1) //p1={沙河娜扎 北京 18}
fmt.Printf("p1=%#v\n", p1) //p1=main.person{name:"沙河娜扎", city:"北京", age:18}
}
우리 .
필드 (멤버 변수)는 예를 들어 구조를 액세스하기 위해 p1.name
그리고 p1.age
등등.
익명 구조
일부 임시 데이터 구조의 정의에서, 등은 익명 장면 구조를 사용할 수있다.
package main
import (
"fmt"
)
func main() {
var user struct{Name string; Age int}
user.Name = "小王子"
user.Age = 18
fmt.Printf("%#v\n", user)
}
포인터 형 구조를 만듭니다
우리는 또한 사용할 수있는 new
구조의 주소를 얻을 인스턴스화 키워드 구조. 다음과 같은 형식입니다 :
var p2 = new(person)
fmt.Printf("%T\n", p2) //*main.person
fmt.Printf("p2=%#v\n", p2) //p2=&main.person{name:"", city:"", age:0}
결과에서 우리는이 인쇄 된 것을 볼 수 p2
있는 구조의 포인터.
지원 구조가 이동 언어로 직접 포인터 참고 .
멤버 액세스 구조.
var p2 = new(person)
p2.name = "小王子"
p2.age = 28
p2.city = "上海"
fmt.Printf("p2=%#v\n", p2) //p2=&main.person{name:"小王子", city:"上海", age:28}
인스턴스화의 주소 구조를 촬영
사용 &
어드레스 동작을 페치 본체 구조는 구조의 유형에 해당 new
동작의 예.
p3 := &person{}
fmt.Printf("%T\n", p3) //*main.person
fmt.Printf("p3=%#v\n", p3) //p3=&main.person{name:"", city:"", age:0}
p3.name = "七米"
p3.age = 30
p3.city = "成都"
fmt.Printf("p3=%#v\n", p3) //p3=&main.person{name:"七米", city:"成都", age:30}
p3.name = "七米"
사실, 바닥이다 (*p3).name = "七米"
, 이것은 우리가 달성 할 수 있도록하기 위해 이동 언어 문법 설탕입니다.
구조 초기화
구조의 멤버 변수는 그 유형에 대응하는 값이 제로이고, 초기화되지 않았다.
type person struct {
name string
city string
age int8
}
func main() {
var p4 person
fmt.Printf("p4=%#v\n", p4) //p4=main.person{name:"", city:"", age:0}
}
초기화 키 - 값 쌍을 사용하여
초기화 키 - 값의 구조를 사용할 때, 필드 구조에 대응하는 키 필드의 초기 값이 있어야한다.
p5 := person{
name: "小王子",
city: "北京",
age: 18,
}
fmt.Printf("p5=%#v\n", p5) //p5=main.person{name:"小王子", city:"北京", age:18}
또한, 예를 들어, 구조에 대한 포인터를 초기화 할 열쇠가 될 수 있습니다 :
p6 := &person{
name: "小王子",
city: "北京",
age: 18,
}
fmt.Printf("p6=%#v\n", p6) //p6=&main.person{name:"小王子", city:"北京", age:18}
어떤 초기 값 일부 필드는 필드 쓸 수없는 경우. 이 경우, 값 필드의 초기 값은 필드 타입의 제로 값을 지정하지 않는다.
p7 := &person{
city: "北京",
}
fmt.Printf("p7=%#v\n", p7) //p7=&main.person{name:"", city:"北京", age:0}
초기 값의 목록을 사용하여
키 작성의 값에 직접 쓰기하지 않을 때 초기화하는 구조가 초기화되고, 축약 될 수있다 :
p8 := &person{
"沙河娜扎",
"北京",
28,
}
fmt.Printf("p8=%#v\n", p8) //p8=&main.person{name:"沙河娜扎", city:"北京", age:28}
이 초기화 형식으로, 당신은주의를 지불해야합니다 :
- 모든 필드는 구조를 초기화해야합니다.
- 순서 초기 값을 채우는 것은 구조의 선언에서 필드 순서와 일치해야합니다.
- 방법은 혼합 키 초기화 방법은 없습니다.
메모리 레이아웃 구조
구조는 연속적인 메모리를 점유한다.
type test struct {
a int8
b int8
c int8
d int8
}
n := test{
1, 2, 3, 4,
}
fmt.Printf("n.a %p\n", &n.a)
fmt.Printf("n.b %p\n", &n.b)
fmt.Printf("n.c %p\n", &n.c)
fmt.Printf("n.d %p\n", &n.d)
출력 :
n.a 0xc0000a0060
n.b 0xc0000a0061
n.c 0xc0000a0062
n.d 0xc0000a0063
[] 이동 언어에 대한 고급 지식 읽기 메모리 정렬을 권장 : 이동 바로 메모리에 정렬
인터뷰 질문
무엇 윌 다음 코드의 결과?
type student struct {
name string
age int
}
func main() {
m := make(map[string]*student)
stus := []student{
{name: "小王子", age: 18},
{name: "娜扎", age: 23},
{name: "大王八", age: 9000},
}
for _, stu := range stus {
m[stu.name] = &stu
}
for k, v := range m {
fmt.Println(k, "=>", v.name)
}
}
생성자
우리가 실현을 소유하고, 언어의 구조는 생성자가 없습니다 이동합니다. 예를 들어,의 실현에 아래의 코드 person
생성자입니다. 이 때문에 struct
구조가 더 복잡하면 값 종류, 생성자 구조 유형에 대한 포인터를 리턴하도록 성능 오버 헤드의 값이 비교적 큰 것 사본.
func newPerson(name, city string, age int8) *person {
return &person{
name: name,
city: city,
age: age,
}
}
생성자를 호출
p9 := newPerson("张三", "沙河", 90)
fmt.Printf("%#v\n", p9) //&main.person{name:"张三", city:"沙河", age:90}
방법 및 수신자
언어를 이동하는 方法(Method)
변수 함수의 특정 유형에 대한 작업입니다. 변수의이 특별한 유형이라고 接收者(Receiver)
. 개념은 다른 언어에받는 사람과 유사 this
또는 self
.
이 방법은 다음과 같은 형식으로 정의된다 :
func (接收者变量 接收者类型) 方法名(参数列表) (返回参数) {
函数体
}
그 중,
- 받는 사람 변수 : 매개 변수 이름 공식의 수신자 명명 첫 번째 유형 소문자를받는 사람의 이름을 사용하는 것이 좋습니다 대신
self
,this
등을 임명했다. 예를 들어,Person
변수의 유형을받는 사람 이름을 지정해야합니다p
,Connector
수신기의 유형은 변수를 지정해야c
처럼. - 수신기 입력 : 수신기 유형과 유사한 매개 변수는 포인터와 포인터가 아닌 유형 유형이 될 수 있습니다.
- 메소드 이름, 매개 변수 목록, 반환 매개 변수 : 함수 정의의 특정 형식과 동일합니다.
예를 들면 :
//Person 结构体
type Person struct {
name string
age int8
}
//NewPerson 构造函数
func NewPerson(name string, age int8) *Person {
return &Person{
name: name,
age: age,
}
}
//Dream Person做梦的方法
func (p Person) Dream() {
fmt.Printf("%s的梦想是学好Go语言!\n", p.name)
}
func main() {
p1 := NewPerson("小王子", 25)
p1.Dream()
}
방법 및 차 함수가 방법의 특정 유형에 속하는 모든 유형의 함수가 아니다.
포인터 타입받는 사람
방법 후 변형이 효과적 방법을 호출 할 때 포인터 타입 수신기 포인터의 특성에 의한 조성물의 구조에 대한 포인터, 포인터가 어떤 수신자 부재 변수를 수정. 이 방법은 다른 객체 지향 언어이다 매우 가까이 this
나 self
. 예를 들어, 우리는 Person
추가 SetAge
연령 인스턴스 변수를 수정하는 방법을.
// SetAge 设置p的年龄
// 使用指针接收者
func (p *Person) SetAge(newAge int8) {
p.age = newAge
}
이 메소드가 호출됩니다 :
func main() {
p1 := NewPerson("小王子", 25)
fmt.Println(p1.age) // 25
p1.SetAge(30)
fmt.Println(p1.age) // 30
}
받는 사람의 값 유형
방법은받는 사람 유형의 역할을 소중히 할 때, 실행 언어 코드를 이동 할 때받는 사람의 복사본의 값입니다. 방법에서 당신은받는 사람 멤버 값의받는 사람의 유형의 가치를 얻을 수 있지만 수정 작업의 사본을받는 사람은 변수 자체를 수정할 수 없습니다.
// SetAge2 设置p的年龄
// 使用值接收者
func (p Person) SetAge2(newAge int8) {
p.age = newAge
}
func main() {
p1 := NewPerson("小王子", 25)
p1.Dream()
fmt.Println(p1.age) // 25
p1.SetAge2(30) // (*p1).SetAge2(30)
fmt.Println(p1.age) // 25
}
당신은 포인터 타입 수신기를 사용해야하는 경우
- 당신은받는 사람의 값을 수정해야
- 받는 사람은 상대적으로 큰 대형 개체의 비용의 복사본입니다
- 포인터 수신기를 사용하는 방법이 있다면 다른 방법은 포인터받는 사람을 사용해야하므로, 일관성을 확인합니다.
방법의 모든 유형을 추가
이동 언어에서,받는 사람뿐만 아니라 모든 유형 구조 될 수 있습니다 입력 방법의 모든 유형을 가질 수 있습니다. 예를 들어, 우리는에 따라 내장 int
새로운 사용자 정의 유형을 정의하고 우리의 사용자 지정 형식에 메서드를 추가 할 수있는 형식 키워드 형태의 사용.
//MyInt 将int定义为自定义MyInt类型
type MyInt int
//SayHello 为MyInt添加一个SayHello的方法
func (m MyInt) SayHello() {
fmt.Println("Hello, 我是一个int。")
}
func main() {
var m1 MyInt
m1.SayHello() //Hello, 我是一个int。
m1 = 100
fmt.Printf("%#v %T\n", m1, m1) //100 main.MyInt
}
주 : 비 네이티브 유형은 우리가 다른 패키지 유형 정의 방법을 제공 할 수 없음을 의미하는 방법을 정의 할 수 없습니다.
익명 필드 구조
구조는 회원이 문 만 유형에 필드 이름을 필드 수 없습니다,이 필드의 이름이 아닌 익명 필드라고합니다.
//Person 结构体Person类型
type Person struct {
string
int
}
func main() {
p1 := Person{
"小王子",
18,
}
fmt.Printf("%#v\n", p1) //main.Person{string:"北京", int:18}
fmt.Println(p1.string, p1.int) //北京 18
}
필드 이름과 유형 이름에 대한 익명 필드의 디폴트는, 구조에 필요한 필드 이름은 고유해야하므로 필드의 같은 익명 형식의 구조는 하나를 가질 수 있습니다.
중첩 구조
구조적 본체는 중첩 구조 또는 다른 구조에 대한 포인터를 포함 할 수있다.
//Address 地址结构体
type Address struct {
Province string
City string
}
//User 用户结构体
type User struct {
Name string
Gender string
Address Address
}
func main() {
user1 := User{
Name: "小王子",
Gender: "男",
Address: Address{
Province: "山东",
City: "威海",
},
}
fmt.Printf("user1=%#v\n", user1)//user1=main.User{Name:"小王子", Gender:"男", Address:main.Address{Province:"山东", City:"威海"}}
}
익명 중첩 된 구조
//Address 地址结构体
type Address struct {
Province string
City string
}
//User 用户结构体
type User struct {
Name string
Gender string
Address //匿名结构体
}
func main() {
var user2 User
user2.Name = "小王子"
user2.Gender = "男"
user2.Address.Province = "山东" //通过匿名结构体.字段名访问
user2.City = "威海" //直接访问匿名结构体的字段名
fmt.Printf("user2=%#v\n", user2) //user2=main.User{Name:"小王子", Gender:"男", Address:main.Address{Province:"山东", City:"威海"}}
}
구조체 멤버에 액세스 할 때 우리는 먼저 익명의 구조를가는 모습을 찾을 수없는 구조에서 필드를 찾을 수 있습니다.
필드 이름이 충돌 중첩 구조
동일한 필드 이름에 존재 내부 중첩 구조. 모호성을 피하기 위해이 시간은 내장 된 구조의 특정 필드를 지정해야합니다.
//Address 地址结构体
type Address struct {
Province string
City string
CreateTime string
}
//Email 邮箱结构体
type Email struct {
Account string
CreateTime string
}
//User 用户结构体
type User struct {
Name string
Gender string
Address
Email
}
func main() {
var user3 User
user3.Name = "沙河娜扎"
user3.Gender = "男"
// user3.CreateTime = "2019" //ambiguous selector user3.CreateTime
user3.Address.CreateTime = "2000" //指定Address结构体中的CreateTime
user3.Email.CreateTime = "2000" //指定Email结构体中的CreateTime
}
구조 "상속"
구조에 사용되는 이동 언어는 다른 프로그래밍 언어, 객체 지향 상속 구현 될 수있다.
//Animal 动物
type Animal struct {
name string
}
func (a *Animal) move() {
fmt.Printf("%s会动!\n", a.name)
}
//Dog 狗
type Dog struct {
Feet int8
*Animal //通过嵌套匿名结构体实现继承
}
func (d *Dog) wang() {
fmt.Printf("%s会汪汪汪~\n", d.name)
}
func main() {
d1 := &Dog{
Feet: 4,
Animal: &Animal{ //注意嵌套的是结构体指针
name: "乐乐",
},
}
d1.wang() //乐乐会汪汪汪~
d1.move() //乐乐会动!
}
가시성 필드 구조
필드 구조의 시작은 공개적으로 액세스 대문자로 표시에서, 소문자는 개인 (단지 현재의 패킷 구조 정의에 액세스 할 수있다)을 나타낸다.
시퀀스 및 JSON의 구조
JSON (JavaScript Object Notation)은 경량 데이터 교환 형식입니다. 쉽게 읽고 쓸 수 있습니다. 기계가 분석하고 생성하는 것은 간단합니다. JSON 키 - 값 쌍 방법 JS 객체 키 / 값 쌍 조합 키 따옴표 사설 저장하는 데 사용되는 ""
결장, 래핑을 :
값으로 단락 지어진 후이어서, 복수의 사이 영 키 ,
구분 .
//Student 学生
type Student struct {
ID int
Gender string
Name string
}
//Class 班级
type Class struct {
Title string
Students []*Student
}
func main() {
c := &Class{
Title: "101",
Students: make([]*Student, 0, 200),
}
for i := 0; i < 10; i++ {
stu := &Student{
Name: fmt.Sprintf("stu%02d", i),
Gender: "男",
ID: i,
}
c.Students = append(c.Students, stu)
}
//JSON序列化:结构体-->JSON格式的字符串
data, err := json.Marshal(c)
if err != nil {
fmt.Println("json marshal failed")
return
}
fmt.Printf("json:%s\n", data)
//JSON反序列化:JSON格式的字符串-->结构体
str := `{"Title":"101","Students":[{"ID":0,"Gender":"男","Name":"stu00"},{"ID":1,"Gender":"男","Name":"stu01"},{"ID":2,"Gender":"男","Name":"stu02"},{"ID":3,"Gender":"男","Name":"stu03"},{"ID":4,"Gender":"男","Name":"stu04"},{"ID":5,"Gender":"男","Name":"stu05"},{"ID":6,"Gender":"男","Name":"stu06"},{"ID":7,"Gender":"男","Name":"stu07"},{"ID":8,"Gender":"男","Name":"stu08"},{"ID":9,"Gender":"男","Name":"stu09"}]}`
c1 := &Class{}
err = json.Unmarshal([]byte(str), c1)
if err != nil {
fmt.Println("json unmarshal failed!")
return
}
fmt.Printf("%#v\n", c1)
}
구조 태그 (태그)
Tag
메타 정보 구조는 런타임 반사에 메커니즘에 의해 판독 할 수있다. Tag
안티 랩 시세, 특히 다음과 같은 형식의 한 쌍의 필드에 상기 정의 된 구조, 후 :
`key1:"value1" key2:"value2"`
하나 이상의 키 - 값 쌍의 구조 라벨. 키와 값은 콜론, 따옴표의 값으로 구분. 쌍 사이에 구분 된 공간을 사용합니다. 참고 : 구조에 대한 서면 Tag
, 우리는 엄격하게 키 - 값 쌍의 규칙을 준수해야합니다. 코드 라벨 구조를 해결하기위한 결함 허용 형식이 잘못되면, 컴파일시 에러 메시지를 표시하지 않습니다 및 런타임, 정확하지 않을 수있는 값을 반영하여, 좋지 않습니다. 예를 들어, 키와 값 사이에 공백을 추가하지 마십시오.
예를 들어, 우리는 Student
구조 JSON 직렬화 태그의 각 필드의 정의를 사용합니다 :
//Student 学生
type Student struct {
ID int `json:"id"` //通过指定tag实现json序列化该字段时的key
Gender string //json序列化是默认使用字段名作为key
name string //私有不能被json包访问
}
func main() {
s1 := Student{
ID: 1,
Gender: "男",
name: "沙河娜扎",
}
data, err := json.Marshal(s1)
if err != nil {
fmt.Println("json marshal failed!")
return
}
fmt.Printf("json str:%s\n", data) //json str:{"id":1,"Gender":"男"}
}
연습 문제
- 학생 정보 관리 시스템을 준비하기 위해 생각의 "객체 지향"방법을 사용합니다.
- ID, 이름, 나이, 점수 및 기타 정보 학생
- 프로그램은 학생, 학생 및 기타 기능을, 목록을 표시 학생, 학생 정보 편집, 추가, 삭제 제공