sách gpt4 ăn đã đi

Thảo luận ngắn về phản ánh cấu trúc trong ngôn ngữ Go

In lại Tác giả: qq735679552 Thời gian cập nhật: 29-09-2022 22:32:09 31 4
mua khóa gpt4 giày nike

CFSDN nhấn mạnh vào giá trị tạo ra nguồn mở và chúng tôi cam kết xây dựng nền tảng chia sẻ tài nguyên để mọi nhân viên CNTT có thể tìm thấy thế giới tuyệt vời của bạn tại đây.

Bài viết trên blog CFSDN này nói sơ qua về sự phản ánh cấu trúc trong ngôn ngữ Go được tác giả sưu tầm và biên soạn. Nếu các bạn quan tâm đến bài viết này thì nhớ like nhé.

Cấu trúc cấu trúc.

struct được sử dụng để tùy chỉnh các cấu trúc dữ liệu phức tạp, có thể chứa nhiều trường (thuộc tính) và có thể lồng nhau;

Kiểu cấu trúc trong go được hiểu là một lớp và các phương thức có thể được định nghĩa, hơi khác so với định nghĩa hàm;

Kiểu cấu trúc là một kiểu giá trị.

định nghĩa cấu trúc

?
1
2
3
4
5
Kiểu người dùng struct {
  Chuỗi tên
  Tuổi int32
  chuỗi lộn xộn
}
?
1
2
3
của chúng tôi người dùng Người dùng
của chúng tôi user1 *Người dùng = &Người dùng{}
của chúng tôi user2 *Người dùng = mới (Người dùng)

sử dụng cấu trúc.

Trong ví dụ sau, user1 và user2 là các loại con trỏ. Khi được truy cập, trình biên dịch sẽ tự động chuyển đổi user1.Name thành (*user1).Name.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
hàm main() {
  là người dùng
  người dùng.Tên = "nick"
  người dùng.Tuổi = 18
  user.mess = "người yêu"
 
  var user1 *Người dùng = &Người dùng{
   Tên: "bình minh",
   Tuổi: 21,
  }
  fmt.Println(*user1) //{bình minh 21 }
  fmt.Println(user1.Name, (*user1).Name) //bình minh bình minh
 
  var user2 *Người dùng = new(Người dùng)
  user2.Name = "sooning"
  user2.Tuổi = 18
  fmt.Println(user2) //&{sooning 18 }
  fmt.Println(user2.Name, (*user2).Name) //sắp xếp thứ tự
}

Người xây dựng.

Cấu trúc trong golang không có hàm tạo, bạn có thể giả mạo nó.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Kiểu người dùng struct {
  Chuỗi tên
  Tuổi int32
  chuỗi lộn xộn
}
 
func NewUser(tên chuỗi, tuổi int32, chuỗi mess) *User {
  trả về &User{Tên:tên,Tuổi:tuổi,mess:mess}
}
 
hàm main() {
  //người dùng := new(Người dùng)
  người dùng := Người dùng mới("suoning", 18, "người yêu")
  fmt.Println(người dùng, người dùng.mess, người dùng.Tên, người dùng.Tuổi)
}

Bố cục bộ nhớ.

Tất cả các trường trong cấu trúc đều liền kề nhau trong bộ nhớ.

?
1
2
3
4
5
6
7
8
9
là người dùng
  người dùng.Tên = "nick"
  người dùng.Tuổi = 18
  user.mess = "người yêu"
 
  fmt.Println(user) //{nick 18 người yêu}
  fmt.Printf("Tên:%p\n", &user.Name) //Tên:0xc420016180
  fmt.Printf("Tuổi: %p\n", &user.Age) //Tuổi: 0xc420016190
  fmt.Printf("mess:%p\n", &user.mess) //mess:0xc420016198 8 byte là căn chỉnh bộ nhớ

phương pháp.

Các phương thức hoạt động trên các biến của một loại cụ thể, do đó, bất kỳ loại tùy chỉnh nào cũng có thể có các phương thức, không chỉ cấu trúc.

Kiểm soát truy cập của các phương pháp cũng được kiểm soát theo từng trường hợp.

Hàm init được triển khai bằng cách truyền vào một con trỏ, con trỏ này sẽ thay đổi giá trị trường cấu trúc vì đây là một loại giá trị.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Kiểu người dùng struct {
  Chuỗi tên
  Tuổi
  dây sex
}
 
func (this *User) init(tên chuỗi, tuổi int, giới tính chuỗi) {
  this.Name = tên
  này.Tuổi = tuổi
  this.sex = tình dục
}
 
func (Người dùng này) GetName() string {
  trả lại cái này.Tên
}
 
hàm main() {
  là người dùng
  user.init("nick", 18, "man")
  //(&user).init("nick", 18, "man")
  tên := người dùng.GetName()
  fmt.Println(tên)
}

Các trường ẩn danh.

Nếu có xung đột thì bên ngoài cùng được ưu tiên.

?
1
2
3
4
5
6
7
8
9
10
11
Kiểu người dùng struct {
  Tên khuấy động
  Tuổi 
}
 
loại Lover struct {
   Người sử dụng
   thời gian quan hệ tình dục.Thời gian
   số nguyên
   Tuổi
}

Kế thừa & Đa kế thừa.

Một cấu trúc kế thừa nhiều cấu trúc và được truy cập thông qua các điểm. Các trường và phương thức được kế thừa.

Bạn có thể sử dụng bí danh, chẳng hạn như u1 (user1) bên dưới, để truy cập user.u1.Age.

Nếu tất cả các cấu trúc được kế thừa đều có cùng một trường thì lỗi sẽ được báo cáo khi truy cập thông qua user.name và phải được truy cập thông qua user.user1.name.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
kiểu user1 struct {
  chuỗi tên
  Tuổi
}
 
loại user2 struct {
  chuỗi tên
  tuổi
  thời gian quan hệ tình dục.Thời gian
}
 
Kiểu người dùng struct {
  u1 người dùng1 //bí danh
  người dùng2
  Chuỗi tên
  Tuổi
}
 
hàm main() {
  là người dùng
  người dùng.Tên = "nick"
  người dùng.u1.Tuổi = 18
  fmt.Println(người dùng) //{{ 18} { 0 {0 0 < không >}} biệt danh 0}
}

nhãn .

Trong go, chữ cái đầu tiên có ý nghĩa ngữ pháp đặc biệt và không thể được trích dẫn bên ngoài gói chữ thường. Do nhu cầu tương tác với các hệ thống khác, chẳng hạn như chuyển đổi sang định dạng json. Tại thời điểm này, nếu bạn sử dụng tên thuộc tính làm giá trị khóa, nó có thể không nhất thiết đáp ứng được yêu cầu của dự án. Khi thẻ được chuyển đổi sang các định dạng dữ liệu khác, các trường cụ thể sẽ được sử dụng làm giá trị khóa.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
nhập "encoding/json"
 
Kiểu người dùng struct {
  Chuỗi tên `json:"userName"`
  Tuổi int `json:"userAge"`
}
 
hàm main() {
  là người dùng
  người dùng.Tên = "nick"
  người dùng.Tuổi = 18
 
  conJson, _ := json.Marshal(người dùng)
  fmt.Println(chuỗi(conJson)) //{"userName":"nick","userAge":0}
}

Sợi dây() .

Nếu phương thức String() được triển khai, fmt sẽ gọi String() theo mặc định.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
kiểu name1 struct {
  số nguyên
  sợi dây
}
 
func (this *name1) String() chuỗi {
  trả về fmt.Sprintf("Đây là String(%s).", this.string)
}
 
hàm main() {
  n := new(tên1)
  fmt.Println(n) //Đây là String().
  n.string = "sooning"
  d := fmt.Sprintf("%s", n) //Đây là String(suoning).
  fmt.Println(d)
}

Giao diện.

Loại Giao diện có thể xác định một tập hợp các phương thức, nhưng những phương thức này không cần phải được triển khai. Và giao diện không thể chứa bất kỳ biến nào.

Kiểu giao diện mặc định là một con trỏ.

Định nghĩa giao diện.

?
1
2
3
4
5
loại Giao diện ô tô {
  Chuỗi NameGet()
  Chạy(n int)
  Dừng lại()
}

Triển khai giao diện.

Các giao diện trong Golang không yêu cầu triển khai rõ ràng. Miễn là một biến chứa tất cả các phương thức trong loại giao diện thì biến này sẽ triển khai giao diện. Do đó, không có từ khóa giống như triển khai trong golang;

Nếu một biến chứa nhiều phương thức loại giao diện thì biến đó thực hiện nhiều giao diện; nếu một biến chỉ chứa một phần phương thức giao diện thì biến đó không triển khai giao diện.

Giao diện trống Giao diện{}: Giao diện trống không có bất kỳ phương thức nào, vì vậy tất cả các loại đều triển khai giao diện trống.

?
1
2
3
đã đi đến int
giao diện var b{} //Giao diện trống
b = một

Đa hình.

Nhiều dạng của một vật đều có thể được vận hành theo một giao diện thống nhất.

hạt dẻ:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
loại Giao diện ô tô {
  Chuỗi NameGet()
  Chạy(n int)
  Dừng lại()
}
 
kiểu BMW struct {
  Chuỗi tên
}
func (this *BMW) NameGet() chuỗi {
  trả lại cái này.Tên
}
func (this *BMW) Chạy(n int) {
  fmt.Printf("BMW đang chạy với số là %d \n", n)
}
func (chiếc *BMW này) Stop() {
  fmt.Printf("BMW dừng lại \n")
}
 
kiểu Benz struct {
  Chuỗi tên
}
func (this *Benz) NameGet() chuỗi {
  trả lại cái này.Tên
}
func (này *Benz) Chạy(n int) {
  fmt.Printf("Benz đang chạy với số là %d \n", n)
}
func (cái này *Benz) Stop() {
  fmt.Printf("Benz dừng lại \n")
}
func (cái này *Benz) ChatUp() {
  fmt.Printf("Trò chuyện \n")
}
 
hàm main() {
  là xe ô tô
  fmt.Println(xe hơi) // < không >
 
  var bmw BMW = BMW{Tên: "BMW"}
  xe hơi = &bmw
  fmt.Println(car.NameGet()) //BMW
  car.Run(1) //BMW đang chạy với số là 1
  car.Stop() //BMW dừng lại
 
  benz := &Benz{Tên: "大奔"}
  xe hơi = benz
  fmt.Println(car.NameGet()) //Daben
  car.Run(2) //Benz đang chạy với số là 2
  car.Stop() //Benz dừng lại
  //car.ChatUp() //ERROR: car.ChatUp không xác định (kiểu Car không có trường hoặc phương thức ChatUp)
}

Giao diện lồng nhau.

Một giao diện có thể được lồng trong một giao diện khác.

Đó là, hai phương pháp giao diện cần được thực hiện.

?
1
2
3
4
5
6
7
8
9
10
loại Giao diện ô tô {
  Chuỗi NameGet()
  Chạy(n int)
  Dừng lại()
}
 
loại Giao diện đã sử dụng {
  Xe hơi
  Rẻ()
}

Khẳng định kiểu.

Xác nhận loại, vì giao diện là loại chung và không biết loại cụ thể.

Nếu bạn muốn chuyển đổi sang một loại cụ thể, bạn có thể sử dụng các phương pháp sau để chuyển đổi:

?
1
2
3
4
5
6
var t int
var x giao diện{}
x = t
 
y = x.(int) //Chuyển sang int
y, ok = x.(int) //Chuyển sang int, sẽ không báo lỗi

Hạt dẻ 1:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func test(i giao diện{}) {
  // n := i.(số nguyên)
  n, ok := i.(int)
  nếu !ok {
   fmt.Println("lỗi")
   trở lại
  }
  n += 10
  fmt.Println(n)
}
 
hàm main() {
  là t1 int
  kiểm tra(t1)
}

Hạt dẻ 2:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
chuyển đổi & loại
 
 
kiểu Học sinh struct {
  Chuỗi tên
}
 
func judgeType(items ...interface{}) {
  đối với k, v := phạm vi các mục {
   chuyển đổi v.(kiểu) {
   chuỗi trường hợp:
    fmt.Printf("chuỗi, %d[%v]\n", k, v)
   trường hợp bool:
    fmt.Printf("bool, %d[%v]\n", k, v)
   trường hợp int, int32, int64:
    fmt.Printf("int, %d[%v]\n", k, v)
   trường hợp float32, float64:
    fmt.Printf("float, %d[%v]\n", k, v)
   trường hợp Học sinh:
    fmt.Printf("Sinh viên, %d[%v]\n", k, v)
   trường hợp *Sinh viên:
    fmt.Printf("Sinh viên, %d[%p]\n", k, v)
   }
  }
}
 
hàm main() {
  stu1 := &Student{Tên: "nick"}
  JudgeType(1, 2.2, "học tập", stu1)
}

Hạt Dẻ Ba:

Xác định xem một biến có thực hiện giao diện đã chỉ định hay không.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
loại giao diện Stringer {
  Chuỗi()
}
 
loại giao diện Mystruct {
 
}
loại Mystruct2 struct {
 
}
func (this *Mystruct2) String() chuỗi {
  trở lại ""
}
 
hàm main() {
  var v Mystruct
  var v2 Mystruct2
  v = &v2
 
  nếu sv, ok := v.(Stringer); ok {
   fmt.Printf("%v triển khai String(): %s\n", sv.String());
  }
}

Sự phản xạ.

Gói phản ánh thực hiện phản ánh thời gian chạy, cho phép các chương trình hoạt động trên bất kỳ loại đối tượng nào.

Cách sử dụng thông thường là sử dụng giao diện kiểu tĩnh {} để lưu giá trị.

  Nhận thông tin loại động của nó bằng cách gọi TypeOf, trả về giá trị loại Loại.

  Việc gọi hàm ValueOf trả về giá trị loại Giá trị đại diện cho dữ liệu thời gian chạy.

func TypeOf(i interface{}) Kiểu 。

TypeOf trả về loại giá trị được lưu trong giao diện, TypeOf(nil) sẽ trả về nil.

func ValueOf(i interface{}) Giá trị 。

ValueOf trả về Giá trị được khởi tạo cho giá trị cụ thể được giữ bởi giao diện i và ValueOf(nil) trả về Giá trị bằng 0.

phản ánh.Giá trị.Loại 。

Lấy danh mục của một biến và trả về một hằng số.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
hằng số (
  Loại không hợp lệ = iota
  Bool
  Int
  Int8
  Int16
  Int32
  Int64
  Đơn vị
  Uint8
  Uint16
  Uint32
  Uint64
  uintptr
  Phao32
  Phao64
  Phức hợp64
  Phức hợp128
  Mảng
  Chân
  Chức năng
  Giao diện
  Bản đồ
  Con trỏ
  Lát cắt
  Sợi dây
  Cấu trúc
  Con trỏ không an toàn
)
 
Hằng số được trả về bởi phương thức Reflect.Value.Kind()

phản ánh.Giá trị.Giao diện() 。

Chuyển đổi sang loại giao diện {}.

【变量<-->Giao diện{<-->Reflect.Value】 。

Lấy giá trị của một biến:

?
1
2
3
4
phản ánh.ValueOf(x).Int()
phản ánh.ValueOf(x).Float()
phản ánh.ValueOf(x).String()
phản ánh.ValueOf(x).Bool()

Thay đổi giá trị của một biến thông qua sự phản ánh.

?
1
2
3
4
Các phương thức liên quan đến Reflect.Value.SetXX, chẳng hạn như:
phản ánh.Value.SetInt(), đặt số nguyên
phản ánh.Value.SetFloat(), đặt số dấu phẩy động
phản ánh.Value.SetString(), đặt chuỗi

Hạt dẻ một.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
nhập khẩu "phản ánh"
 
hàm main() {
  var x float64 = 5,21
  fmt.Println("kiểu:", reflect.TypeOf(x)) //kiểu: float64
 
  v := phản ánh.ValueOf(x)
  fmt.Println("giá trị:", v) //giá trị: 5.21
  fmt.Println("kiểu:", v.Type()) //kiểu: float64
  fmt.Println("loại:", v.Kind()) //loại: float64
  fmt.Println("giá trị:", v.Float()) //giá trị: 5.21
 
  fmt.Println(v.Giao diện()) //5.21
  fmt.Printf("giá trị là %1.1e\n", v.Interface()) //giá trị là 5.2e+00
  y := v.Giao diện().(float64)
  fmt.Println(y) //5.21
}

Hạt dẻ 2 (giá trị được sửa đổi).

SetXX(x) Vì nó truyền một bản sao của giá trị x nên SetXX không thể thay đổi x. Để thay đổi x, bạn phải truyền con trỏ của x cho hàm SetXX(&x).

?
1
2
3
4
5
6
7
8
//Mã lỗi! ! !
//panic: reflect: reflect.Value.SetFloat sử dụng giá trị không thể định địa chỉ
hàm main() {
  là một cái phao64
  fv := phản ánh.ValueOf(&a)
  fv.SetFloat(520.00)
  fmt.Printf("%v\n", a)
}
?
1
2
3
4
5
6
7
// Đúng, truyền con trỏ
hàm main() {
  var a2 float64
  fv2 := phản ánh.ValueOf(&a2)
  fv2.Element().SetFloat(520.00)
  fmt.Printf("%v\n", a2) //520
}

Cấu trúc hoạt động phản ánh.

Reflect.Value.NumField() lấy số lượng trường trong cấu trúc.

phản ánh.Value.Method(n).Call(nil) để gọi phương thức trong cấu trúc.

Hạt dẻ 1 (cấu trúc vận hành thông qua phản ánh).

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
nhập khẩu "phản ánh"
 
kiểu NotknownType struct {
  Dây S1
  Dây S2
  Chuỗi S3
}
 
func (n NotknownType) String() chuỗi {
  trả về n.S1 + " & " + n.S2 + " & " + n.S3
}
 
var secret interface{} = NotknownType{"Go", "C", "Python"}
 
hàm main() {
  giá trị := phản ánh.Giá trị của(bí mật)
  fmt.Println(giá trị) //Go & C & Python
  typ := phản ánh.TypeOf(bí mật)
  fmt.Println(loại) //main.NotknownType
 
  knd := giá trị.Kind()
  fmt.Println(knd) // cấu trúc
 
  đối với i := 0; i < giá trị.NumField(); i++ {
   fmt.Printf("Trường %d: %v\n", i, giá trị.Trường(i))
  }
 
  kết quả := giá trị.Phương pháp(0).Gọi(nil)
  fmt.Println(kết quả) // [Go & C & Python]
}

Chestnut 2 (sửa đổi cấu trúc thông qua sự phản chiếu).

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
nhập khẩu "phản ánh"
 
kiểu T struct {
  Một số nguyên
  Dây B
}
 
hàm main() {
  t := T{18, "biệt danh"}
  s := phản ánh.ValueOf(&t).Elem()
  typeOfT := s.Type()
 
  đối với i := 0; i < s.NumField(); i++ {
   f := s. Trường(i)
   fmt.Printf("%d: %s %s = %v\n", tôi,
    typeOfT.Field(i).Name, f.Type(), f.Interface())
  }
 
  s. Trường(0). ĐặtInt(25)
  s.Field(1).SetString("nicky")
  fmt.Println(t)
}
 
/*
Đầu ra:
0: Một số nguyên = 18
1: Dây B = nick
{25 nick}
*/
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
nhập khẩu "phản ánh"
 
kiểu kiểm tra struct {
  Dây S1
  chuỗi s2
  chuỗi s3
}
 
var s giao diện{} = &test{
  S1: "s1",
  s2: "s2",
  s3: "s3",
}
 
hàm main() {
  val := phản ánh.ValueOf(s)
  fmt.Println(val) //&{s1 s2 s3}
  fmt.Println(val.Elem()) //{s1 s2 s3}
  fmt.Println(val.Elem().Field(0)) //s1
  val.Elem().Field(0).SetString("hehe") //S1 viết hoa
}

Chestnut 3 (triển khai nội bộ thẻ struct).

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
gói chính
 
nhập khẩu (
  "fmt"
  "phản ánh"
)
 
Kiểu người dùng struct {
  Chuỗi tên `json:"user_name"`
}
 
hàm main() {
  là người dùng
  userType := phản ánh.TypeOf(người dùng)
  jsonString := userType.Field(0).Tag.Get("json")
  fmt.Println(jsonString) //tên_người_dùng
}

Bài viết trên nói sơ qua về cấu trúc & giao diện & phản chiếu trong ngôn ngữ Go. Đây là toàn bộ nội dung mà editor đã chia sẻ với các bạn, mong các bạn tham khảo và mong các bạn ủng hộ mình nhiều. .

Cuối cùng, bài viết thảo luận ngắn gọn về phản ánh cấu trúc trong ngôn ngữ Go kết thúc ở đây. Nếu bạn muốn biết thêm về một cuộc thảo luận ngắn gọn về phản ánh cấu trúc trong ngôn ngữ Go, vui lòng tìm kiếm các bài viết của CFSDN hoặc tiếp tục duyệt các bài viết liên quan. bạn sẽ ủng hộ blog của tôi trong tương lai! .

31 4 0
qq735679552
Hồ sơ

Tôi là một lập trình viên xuất sắc, rất giỏi!

Nhận phiếu giảm giá taxi Didi miễn phí
Phiếu giảm giá taxi Didi
Chứng chỉ ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com
Xem sitemap của VNExpress