Go - Hướng dẫn nhanh

Go là một ngôn ngữ có mục đích chung được thiết kế với mục đích lập trình hệ thống. Ban đầu, nó được phát triển tại Google vào năm 2007 bởi Robert Griesemer, Rob Pike và Ken Thompson. Nó được gõ mạnh và tĩnh, cung cấp hỗ trợ sẵn có để thu gom rác và hỗ trợ lập trình đồng thời.

Các chương trình được xây dựng bằng cách sử dụng các gói, để quản lý hiệu quả các phần phụ thuộc. Các triển khai lập trình Go sử dụng mô hình biên dịch và liên kết truyền thống để tạo các tệp nhị phân thực thi. Ngôn ngữ lập trình Go được công bố vào tháng 11 năm 2009 và được sử dụng trong một số hệ thống sản xuất của Google.

Các tính năng của lập trình Go

Các tính năng quan trọng nhất của lập trình cờ vây được liệt kê dưới đây:

  • Hỗ trợ môi trường áp dụng các mẫu tương tự như các ngôn ngữ động. Ví dụ, kiểu suy luận (x: = 0 là khai báo hợp lệ của một biến x kiểu int)

  • Thời gian biên dịch nhanh chóng.

  • Hỗ trợ đồng thời sẵn có: các quy trình nhẹ (thông qua các thói quen đi), kênh, câu lệnh chọn.

  • Các chương trình cờ vây rất đơn giản, ngắn gọn và an toàn.

  • Hỗ trợ nhúng Giao diện và Kiểu.

  • Sản xuất các tệp nhị phân gốc được liên kết tĩnh mà không có phụ thuộc bên ngoài.

Các tính năng cố ý bị loại trừ

Để giữ cho ngôn ngữ đơn giản và ngắn gọn, các tính năng sau thường có sẵn trong các ngôn ngữ tương tự khác sẽ bị bỏ qua trong Go -

  • Hỗ trợ kiểu kế thừa

  • Hỗ trợ quá tải phương thức hoặc toán tử

  • Hỗ trợ sự phụ thuộc vòng tròn giữa các gói

  • Hỗ trợ số học con trỏ

  • Hỗ trợ cho các xác nhận

  • Hỗ trợ lập trình chung

Đi chương trình

Một chương trình cờ vây có thể có độ dài khác nhau từ 3 dòng đến hàng triệu dòng và nó phải được viết thành một hoặc nhiều tệp văn bản có phần mở rộng là ".go". Ví dụ, hello.go.

Bạn có thể sử dụng "vi", "vim" hoặc bất kỳ trình soạn thảo văn bản nào khác để viết chương trình Go của bạn thành một tệp.

Thiết lập môi trường cục bộ

Nếu bạn vẫn sẵn sàng thiết lập môi trường của mình cho ngôn ngữ lập trình Go, bạn cần có hai phần mềm sau trên máy tính của mình:

  • Một trình soạn thảo văn bản
  • Tới trình biên dịch

Trình soạn thảo văn bản

Bạn sẽ cần một trình soạn thảo văn bản để nhập các chương trình của mình. Ví dụ về trình soạn thảo văn bản bao gồm Windows Notepad, lệnh Chỉnh sửa hệ điều hành, Tóm tắt, Epsilon, EMACS và vim hoặc vi.

Tên và phiên bản của trình soạn thảo văn bản có thể khác nhau trên các hệ điều hành khác nhau. Ví dụ: Notepad được sử dụng trên Windows và vim hoặc vi được sử dụng trên Windows cũng như Linux hoặc UNIX.

Các tệp bạn tạo bằng trình soạn thảo văn bản được gọi là source files. Chúng chứa mã nguồn chương trình. Các tệp nguồn cho các chương trình Go thường được đặt tên với phần mở rộng".go".

Trước khi bắt đầu lập trình, hãy đảm bảo rằng bạn đã có sẵn một trình soạn thảo văn bản và bạn có đủ kinh nghiệm để viết một chương trình máy tính, lưu nó vào một tệp, biên dịch và cuối cùng là thực thi nó.

Trình biên dịch Go

Mã nguồn được viết trong tệp nguồn là nguồn con người có thể đọc được cho chương trình của bạn. Nó cần được biên dịch và chuyển thành ngôn ngữ máy để CPU của bạn có thể thực thi chương trình theo hướng dẫn được đưa ra. Trình biên dịch ngôn ngữ lập trình Go biên dịch mã nguồn thành chương trình thực thi cuối cùng của nó.

Bản phân phối Go có thể cài đặt dưới dạng nhị phân cho FreeBSD (phiên bản 8 trở lên), Linux, Mac OS X (Snow Leopard trở lên) và hệ điều hành Windows với kiến ​​trúc bộ xử lý x86 32 bit (386) và 64 bit (amd64).

Phần sau giải thích cách cài đặt phân phối nhị phân Go trên các hệ điều hành khác nhau.

Tải xuống Go Archive

Tải xuống phiên bản mới nhất của tệp lưu trữ có thể cài đặt Go từ Go Downloads . Phiên bản sau được sử dụng trong hướng dẫn này: go1.4.windows-amd64.msi .

Nó được sao chép nó vào thư mục C: \> go.

Hệ điều hành Tên lưu trữ
các cửa sổ go1.4.windows-amd64.msi
Linux go1.4.linux-amd64.tar.gz
Mac go1.4.darwin-amd64-osx10.8.pkg
FreeBSD go1.4.freebsd-amd64.tar.gz

Cài đặt trên UNIX / Linux / Mac OS X và FreeBSD

Giải nén kho lưu trữ tải xuống vào thư mục / usr / local, tạo một cây Go trong / usr / local / go. Ví dụ -

tar -C / usr / local -xzf go1.4.linux-amd64.tar.gz

Thêm / usr / local / go / bin vào biến môi trường PATH.

Hệ điều hành Đầu ra
Linux xuất PATH = $ PATH: / usr / local / go / bin
Mac xuất PATH = $ PATH: / usr / local / go / bin
FreeBSD xuất PATH = $ PATH: / usr / local / go / bin

Cài đặt trên Windows

Sử dụng tệp MSI và làm theo lời nhắc để cài đặt công cụ Go. Theo mặc định, trình cài đặt sử dụng phân phối Go trong c: \ Go. Trình cài đặt nên đặt thư mục c: \ Go \ bin trong biến môi trường PATH của Window. Khởi động lại mọi lời nhắc lệnh đang mở để thay đổi có hiệu lực.

Xác minh cài đặt

Tạo một tệp go có tên test.go in C:\>Go_WorkSpace.

Tệp: test.go

package main

import "fmt"

func main() {
   fmt.Println("Hello, World!")
}

Bây giờ hãy chạy test.go để xem kết quả -

C:\Go_WorkSpace>go run test.go

Đầu ra

Hello, World!

Trước khi chúng ta nghiên cứu các khối xây dựng cơ bản của ngôn ngữ lập trình Go, trước tiên chúng ta hãy thảo luận về cấu trúc tối thiểu của các chương trình Go để chúng ta có thể lấy nó làm tài liệu tham khảo trong các chương tiếp theo.

Ví dụ về Hello World

Một chương trình cờ vây về cơ bản bao gồm các phần sau:

  • Khai báo gói hàng
  • Nhập gói
  • Functions
  • Variables
  • Tuyên bố và biểu thức
  • Comments

Chúng ta hãy xem một đoạn mã đơn giản có in dòng chữ "Hello World" -

package main

import "fmt"

func main() {
   /* This is my first sample program. */
   fmt.Println("Hello, World!")
}

Chúng ta hãy xem xét các phần khác nhau của chương trình trên -

  • Dòng đầu tiên của gói chương trình chính xác định tên gói mà chương trình này sẽ nằm trong đó. Đây là một tuyên bố bắt buộc, vì các chương trình Go chạy trong các gói. Gói chính là điểm bắt đầu để chạy chương trình. Mỗi gói có một đường dẫn và tên được liên kết với nó.

  • Nhập dòng tiếp theo "fmt" là lệnh tiền xử lý yêu cầu trình biên dịch Go bao gồm các tệp nằm trong gói fmt.

  • Dòng tiếp theo func main () là hàm chính bắt đầu thực thi chương trình.

  • Dòng tiếp theo /*...*/ bị trình biên dịch bỏ qua và nó ở đó để thêm nhận xét trong chương trình. Chú thích cũng được biểu diễn bằng cách sử dụng // tương tự như chú thích của Java hoặc C ++.

  • Dòng tiếp theo fmt.Println (...) là một hàm khác có sẵn trong Go gây ra thông báo "Hello, World!" được hiển thị trên màn hình. Ở đây gói fmt đã xuất ra phương thức Println dùng để hiển thị thông báo trên màn hình.

  • Chú ý chữ P viết hoa của phương pháp Println. Trong ngôn ngữ cờ vây, tên sẽ được xuất nếu nó bắt đầu bằng chữ in hoa. Đã xuất có nghĩa là hàm hoặc biến / hằng có thể truy cập được đối với nhà nhập khẩu gói tương ứng.

Thực hiện một chương trình cờ vây

Hãy để chúng tôi thảo luận về cách lưu mã nguồn trong một tệp, biên dịch nó và cuối cùng là thực thi chương trình. Vui lòng làm theo các bước dưới đây -

  • Mở trình soạn thảo văn bản và thêm mã được đề cập ở trên.

  • Lưu tệp dưới dạng hello.go

  • Mở dấu nhắc lệnh.

  • Đi tới thư mục mà bạn đã lưu tệp.

  • Nhập go run hello.go và nhấn enter để chạy mã của bạn.

  • Nếu không có lỗi nào trong mã của bạn, thì bạn sẽ thấy "Hello World!" in trên màn hình.

$ go run hello.go
Hello, World!

Đảm bảo rằng trình biên dịch Go có trong đường dẫn của bạn và bạn đang chạy nó trong thư mục chứa tệp nguồn hello.go.

Chúng ta đã thảo luận về cấu trúc cơ bản của chương trình cờ vây trong chương trước. Bây giờ sẽ dễ dàng hiểu được các khối xây dựng cơ bản khác của ngôn ngữ lập trình Go.

Mã thông báo trong Go

Một chương trình cờ vây bao gồm các mã thông báo khác nhau. Mã thông báo là một từ khóa, một mã định danh, một hằng số, một chuỗi ký tự hoặc một ký hiệu. Ví dụ: câu lệnh Go sau đây bao gồm sáu mã thông báo:

fmt.Println("Hello, World!")

Các mã thông báo riêng lẻ là -

fmt
.
Println
(
   "Hello, World!"
)

Dấu phân cách dòng

Trong chương trình Go, khóa phân cách dòng là một dấu chấm dứt câu lệnh. Nghĩa là, các câu lệnh riêng lẻ không cần dấu phân tách đặc biệt như “;” trong C. Trình biên dịch Go đặt nội bộ “;” như là dấu chấm hết câu lệnh để chỉ ra phần cuối của một thực thể logic.

Ví dụ, hãy xem các câu lệnh sau:

fmt.Println("Hello, World!")
fmt.Println("I am in Go Programming World!")

Bình luận

Nhận xét giống như văn bản trợ giúp trong chương trình Go của bạn và chúng bị trình biên dịch bỏ qua. Chúng bắt đầu bằng / * và kết thúc bằng các ký tự * / như hình dưới đây -

/* my first program in Go */

Bạn không thể có nhận xét trong nhận xét và chúng không xảy ra trong một chuỗi hoặc ký tự.

Định danh

Số nhận dạng Go là tên được sử dụng để xác định một biến, hàm hoặc bất kỳ mục nào khác do người dùng xác định. Số nhận dạng bắt đầu bằng chữ cái A đến Z hoặc từ a đến z hoặc dấu gạch dưới _ theo sau là không hoặc nhiều chữ cái, dấu gạch dưới và chữ số (0 đến 9).

định danh = letter {letter | unicode_digit}.

Go không cho phép các ký tự dấu câu như @, $ và% trong số nhận dạng. Go là mộtcase-sensitivengôn ngữ lập trình. Như vậy, Nhân lựcnhân lực là hai định danh khác nhau trong cờ vây. Dưới đây là một số ví dụ về số nhận dạng được chấp nhận -

mahesh      kumar   abc   move_name   a_123
myname50   _temp    j      a23b9      retVal

Từ khóa

Danh sách sau đây hiển thị các từ dành riêng trong cờ vây. Những từ dành riêng này không được dùng làm hằng số hoặc biến hoặc bất kỳ tên định danh nào khác.

phá vỡ mặc định func giao diện lựa chọn
trường hợp hoãn lại Đi bản đồ Cấu trúc
chan khác Đi đến gói hàng Công tắc điện
hăng sô thất bại nếu phạm vi Kiểu
tiếp tục cho nhập khẩu trở về Var

Khoảng trắng trong Go

Khoảng trắng là thuật ngữ được sử dụng trong Go để mô tả khoảng trống, tab, ký tự dòng mới và nhận xét. Một dòng chỉ chứa khoảng trắng, có thể với chú thích, được gọi là dòng trống và trình biên dịch Go hoàn toàn bỏ qua nó.

Khoảng trắng tách một phần của câu lệnh với phần khác và cho phép trình biên dịch xác định vị trí một phần tử trong câu lệnh, chẳng hạn như int, kết thúc và phần tử tiếp theo bắt đầu. Do đó, trong câu lệnh sau:

var age int;

Phải có ít nhất một ký tự khoảng trắng (thường là khoảng trắng) giữa int và age để trình biên dịch có thể phân biệt chúng. Mặt khác, trong câu lệnh sau:

fruit = apples + oranges;   // get the total fruit

Không cần ký tự khoảng trắng nào giữa trái cây và =, hoặc giữa = và táo, mặc dù bạn có thể thêm một số ký tự nếu muốn vì mục đích dễ đọc.

Trong ngôn ngữ lập trình Go, kiểu dữ liệu đề cập đến một hệ thống mở rộng được sử dụng để khai báo các biến hoặc hàm thuộc các kiểu khác nhau. Kiểu của một biến xác định bao nhiêu không gian mà nó chiếm trong bộ nhớ và cách diễn giải mẫu bit được lưu trữ.

Các loại cờ vây có thể được phân loại như sau:

Sr.No. Các loại và Mô tả
1

Boolean types

Chúng là kiểu boolean và bao gồm hai hằng số được xác định trước: (a) true (b) false

2

Numeric types

Chúng lại là kiểu số học và chúng đại diện cho a) kiểu số nguyên hoặc b) giá trị dấu phẩy động trong suốt chương trình.

3

String types

Một kiểu chuỗi đại diện cho tập hợp các giá trị chuỗi. Giá trị của nó là một chuỗi các byte. Chuỗi là kiểu bất biến, khi đã tạo thì không thể thay đổi nội dung của chuỗi. Kiểu chuỗi được khai báo trước là chuỗi.

4

Derived types

Chúng bao gồm (a) Kiểu con trỏ, (b) Kiểu mảng, (c) Kiểu cấu trúc, (d) Kiểu liên kết và (e) Kiểu hàm f) Kiểu lát g) Kiểu giao diện h) Kiểu bản đồ i) Kiểu kênh

Kiểu mảng và kiểu cấu trúc được gọi chung là aggregate types. Kiểu của một hàm chỉ định tập hợp của tất cả các hàm có cùng kiểu tham số và kết quả. Chúng ta sẽ thảo luận về các kiểu cơ bản trong phần sau, trong khi các kiểu khác sẽ được đề cập trong các chương sắp tới.

Các loại số nguyên

Các kiểu số nguyên độc lập với kiến ​​trúc được xác định trước là:

Sr.No. Các loại và Mô tả
1

uint8

Số nguyên 8 bit không dấu (0 đến 255)

2

uint16

Số nguyên 16 bit không dấu (0 đến 65535)

3

uint32

Số nguyên 32 bit không dấu (0 đến 4294967295)

4

uint64

Số nguyên 64 bit không dấu (0 đến 18446744073709551615)

5

int8

Số nguyên 8 bit có dấu (-128 đến 127)

6

int16

Số nguyên 16 bit đã ký (-32768 đến 32767)

7

int32

Số nguyên 32 bit đã ký (-2147483648 đến 2147483647)

số 8

int64

Số nguyên 64 bit đã ký (-9223372036854775808 đến 9223372036854775807)

Các loại nổi

Các kiểu float độc lập với kiến ​​trúc được xác định trước là:

Sr.No. Các loại và Mô tả
1

float32

IEEE-754 số dấu phẩy động 32 bit

2

float64

IEEE-754 số dấu phẩy động 64 bit

3

complex64

Số phức với phần thực và phần ảo float32

4

complex128

Số phức với float64 phần thực và phần ảo

Giá trị của một số nguyên n-bit là n bit và được biểu diễn bằng hai phép toán số học bổ sung.

Các loại số khác

Ngoài ra còn có một tập hợp các kiểu số với kích thước cụ thể cho việc triển khai -

Sr.No. Các loại và Mô tả
1

byte

giống như uint8

2

rune

giống như int32

3

uint

32 hoặc 64 bit

4

int

cùng kích thước với uint

5

uintptr

một số nguyên không dấu để lưu trữ các bit chưa được thông dịch của một giá trị con trỏ

Một biến không là gì khác ngoài tên được đặt cho vùng lưu trữ mà chương trình có thể thao tác. Mỗi biến trong Go có một kiểu cụ thể, xác định kích thước và cách bố trí bộ nhớ của biến, phạm vi giá trị có thể được lưu trữ trong bộ nhớ đó và tập hợp các thao tác có thể áp dụng cho biến.

Tên của một biến có thể bao gồm các chữ cái, chữ số và ký tự gạch dưới. Nó phải bắt đầu bằng một chữ cái hoặc một dấu gạch dưới. Chữ hoa và chữ thường khác nhau vì cờ vây có phân biệt chữ hoa chữ thường. Dựa trên các kiểu cơ bản đã giải thích trong chương trước, sẽ có các kiểu biến cơ bản sau:

Sr.No Loại & Mô tả
1

byte

Điển hình là một octet đơn (một byte). Đây là một kiểu byte.

2

int

Kích thước tự nhiên nhất của số nguyên cho máy.

3

float32

Một giá trị dấu chấm động chính xác duy nhất.

Ngôn ngữ lập trình Go cũng cho phép định nghĩa nhiều loại biến khác nhau như Enumeration, Pointer, Array, Structure và Union, mà chúng ta sẽ thảo luận trong các chương tiếp theo. Trong chương này, chúng ta sẽ chỉ tập trung vào các kiểu biến cơ bản.

Định nghĩa biến trong Go

Định nghĩa biến cho trình biên dịch biết vị trí và dung lượng lưu trữ cần tạo cho biến. Định nghĩa biến chỉ định một kiểu dữ liệu và chứa danh sách một hoặc nhiều biến của kiểu đó như sau:

var variable_list optional_data_type;

Đây, optional_data_type là một kiểu dữ liệu Go hợp lệ bao gồm byte, int, float32, complex64, boolean hoặc bất kỳ đối tượng nào do người dùng xác định, v.v. và variable_listcó thể bao gồm một hoặc nhiều tên định danh được phân tách bằng dấu phẩy. Một số khai báo hợp lệ được hiển thị ở đây -

var  i, j, k int;
var  c, ch byte;
var  f, salary float32;
d =  42;

Tuyên bố “var i, j, k;”khai báo và định nghĩa các biến i, j và k; hướng dẫn trình biên dịch tạo các biến có tên i, j và k kiểu int.

Các biến có thể được khởi tạo (gán giá trị ban đầu) trong khai báo của chúng. Loại biến được trình biên dịch tự động đánh giá dựa trên giá trị được truyền cho nó. Bộ khởi tạo bao gồm một dấu bằng theo sau là một biểu thức hằng số như sau:

variable_name = value;

Ví dụ,

d = 3, f = 5;    // declaration of d and f. Here d and f are int

Đối với định nghĩa không có bộ khởi tạo: các biến có thời lượng lưu trữ tĩnh được khởi tạo ngầm định bằng nil (tất cả các byte đều có giá trị 0); giá trị ban đầu của tất cả các biến khác là giá trị 0 của kiểu dữ liệu của chúng.

Khai báo kiểu tĩnh khi di chuyển

Khai báo biến kiểu tĩnh cung cấp sự đảm bảo cho trình biên dịch rằng có một biến có sẵn với kiểu và tên đã cho để trình biên dịch có thể tiến hành biên dịch thêm mà không yêu cầu chi tiết đầy đủ của biến. Một khai báo biến chỉ có ý nghĩa tại thời điểm biên dịch, trình biên dịch cần khai báo biến thực sự tại thời điểm liên kết của chương trình.

Thí dụ

Hãy thử ví dụ sau, trong đó biến đã được khai báo với một kiểu và được khởi tạo bên trong hàm chính:

package main

import "fmt"

func main() {
   var x float64
   x = 20.0
   fmt.Println(x)
   fmt.Printf("x is of type %T\n", x)
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

20
x is of type float64

Khai báo kiểu động / Suy luận kiểu trong Go

Khai báo biến kiểu động yêu cầu trình biên dịch giải thích kiểu của biến dựa trên giá trị được truyền cho nó. Trình biên dịch không yêu cầu một biến phải có kiểu tĩnh như một yêu cầu cần thiết.

Thí dụ

Hãy thử ví dụ sau, trong đó các biến đã được khai báo mà không có bất kỳ kiểu nào. Lưu ý, trong trường hợp kiểu suy luận, chúng tôi đã khởi tạo biếny với: = toán tử, trong khi x được khởi tạo bằng toán tử =.

package main

import "fmt"

func main() {
   var x float64 = 20.0

   y := 42 
   fmt.Println(x)
   fmt.Println(y)
   fmt.Printf("x is of type %T\n", x)
   fmt.Printf("y is of type %T\n", y)	
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

20
42
x is of type float64
y is of type int

Khai báo biến hỗn hợp khi di chuyển

Các biến của các kiểu khác nhau có thể được khai báo một lần bằng cách sử dụng suy luận kiểu.

Thí dụ

package main

import "fmt"

func main() {
   var a, b, c = 3, 4, "foo"  
	
   fmt.Println(a)
   fmt.Println(b)
   fmt.Println(c)
   fmt.Printf("a is of type %T\n", a)
   fmt.Printf("b is of type %T\n", b)
   fmt.Printf("c is of type %T\n", c)
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

3
4
foo
a is of type int
b is of type int
c is of type string

Giá trị và giá trị trong cờ vây

Có hai loại biểu thức trong cờ vây -

  • lvalue- Các biểu thức tham chiếu đến một vị trí bộ nhớ được gọi là biểu thức "lvalue". Giá trị có thể xuất hiện ở dạng bên trái hoặc bên phải của bài tập.

  • rvalue- Thuật ngữ rvalue đề cập đến một giá trị dữ liệu được lưu trữ tại một số địa chỉ trong bộ nhớ. Giá trị là một biểu thức không thể có giá trị được gán cho nó, có nghĩa là giá trị có thể xuất hiện ở bên phải nhưng không xuất hiện ở bên trái của một phép gán.

Các biến là giá trị và do đó có thể xuất hiện ở phía bên trái của phép gán. Các chữ số là các giá trị và do đó, có thể không được gán và không thể xuất hiện ở phía bên trái.

Câu lệnh sau là hợp lệ -

x = 20.0

Câu lệnh sau không hợp lệ. Nó sẽ tạo ra lỗi thời gian biên dịch -

10 = 20

Hằng số đề cập đến các giá trị cố định mà chương trình không thể thay đổi trong quá trình thực thi. Các giá trị cố định này còn được gọi làliterals.

Hằng số có thể thuộc bất kỳ kiểu dữ liệu cơ bản nào như hằng số nguyên, hằng số động, hằng ký tự hoặc chuỗi ký tự . Ngoài ra còn có các hằng số liệt kê.

Các hằng được xử lý giống như các biến thông thường ngoại trừ việc giá trị của chúng không thể được sửa đổi sau khi định nghĩa.

Chữ số nguyên

Một chữ số nguyên có thể là một hằng số thập phân, bát phân hoặc thập lục phân. Tiền tố chỉ định cơ số hoặc cơ số: 0x hoặc 0X cho hệ thập lục phân, 0 cho hệ bát phân và không có gì cho thập phân.

Một chữ số nguyên cũng có thể có một hậu tố là sự kết hợp của U và L, tương ứng là không dấu và dài. Hậu tố có thể là chữ hoa hoặc chữ thường và có thể theo bất kỳ thứ tự nào.

Dưới đây là một số ví dụ về các ký tự số nguyên -

212         /* Legal */
215u        /* Legal */
0xFeeL      /* Legal */
078         /* Illegal: 8 is not an octal digit */
032UU       /* Illegal: cannot repeat a suffix */

Sau đây là các ví dụ khác về các loại ký tự Số nguyên khác nhau -

85         /* decimal */
0213       /* octal */
0x4b       /* hexadecimal */
30         /* int */
30u        /* unsigned int */
30l        /* long */
30ul       /* unsigned long */

Chữ nổi dấu chấm động

Một ký tự dấu phẩy động có một phần nguyên, một dấu thập phân, một phần thập phân và một phần mũ. Bạn có thể biểu diễn các ký tự dấu phẩy động ở dạng thập phân hoặc dạng hàm mũ.

Trong khi biểu diễn bằng cách sử dụng dạng thập phân, bạn phải bao gồm dấu thập phân, số mũ hoặc cả hai và trong khi biểu diễn bằng cách sử dụng dạng mũ, bạn phải bao gồm phần nguyên, phần thập phân hoặc cả hai. Số mũ có dấu được giới thiệu bởi e hoặc E.

Dưới đây là một số ví dụ về các ký tự dấu phẩy động -

3.14159       /* Legal */
314159E-5L    /* Legal */
510E          /* Illegal: incomplete exponent */
210f          /* Illegal: no decimal or exponent */
.e55          /* Illegal: missing integer or fraction */

Trình tự thoát

Khi một số ký tự đứng trước dấu gạch chéo ngược, chúng sẽ có ý nghĩa đặc biệt trong cờ vây. Chúng được gọi là mã Escape Sequence được sử dụng để đại diện cho dòng mới (\ n), tab (\ t), backspace, v.v. Tại đây, bạn có danh sách một số mã trình tự thoát như vậy -

Trình tự thoát Ý nghĩa
\\ \ tính cách
\ ' ' tính cách
\ " " tính cách
\? ? tính cách
\ a Cảnh báo hoặc chuông
\ b Backspace
\ f Thức ăn dạng
\ n Dòng mới
\ r Vận chuyển trở lại
\ t Tab ngang
\ v Tab dọc
\ ooo Số bát phân từ một đến ba chữ số
\ xhh. . . Số thập lục phân gồm một hoặc nhiều chữ số

Ví dụ sau đây cho thấy cách sử dụng \t trong một chương trình -

package main

import "fmt"

func main() {
   fmt.Printf("Hello\tWorld!")
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

Hello World!

String Literals in Go

Các ký tự hoặc hằng số của chuỗi được đặt trong dấu ngoặc kép "". Một chuỗi chứa các ký tự tương tự như các ký tự: ký tự thuần túy, chuỗi thoát và ký tự phổ quát.

Bạn có thể ngắt một dòng dài thành nhiều dòng bằng cách sử dụng các ký tự chuỗi và phân tách chúng bằng cách sử dụng khoảng trắng.

Dưới đây là một số ví dụ về chuỗi ký tự. Tất cả ba hình thức là các chuỗi giống hệt nhau.

"hello, dear"

"hello, \

dear"

"hello, " "d" "ear"

Các const từ khóa

Bạn có thể dùng const tiền tố để khai báo các hằng với một kiểu cụ thể như sau:

const variable type = value;

Ví dụ sau đây cho thấy cách sử dụng const từ khóa -

package main

import "fmt"

func main() {
   const LENGTH int = 10
   const WIDTH int = 5   
   var area int

   area = LENGTH * WIDTH
   fmt.Printf("value of area : %d", area)   
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

value of area : 50

Lưu ý rằng đó là một thực hành lập trình tốt để xác định hằng số trong CHỮ HOA.

Một toán tử là một ký hiệu yêu cầu trình biên dịch thực hiện các thao tác toán học hoặc logic cụ thể. Ngôn ngữ cờ vây có nhiều toán tử cài sẵn và cung cấp các loại toán tử sau:

  • Toán tử số học
  • Toán tử quan hệ
  • Toán tử logic
  • Toán tử Bitwise
  • Người điều hành nhiệm vụ
  • Các nhà khai thác khác

Hướng dẫn này giải thích từng toán tử số học, quan hệ, logic, bitwise, phép gán và các toán tử khác.

Toán tử số học

Bảng sau hiển thị tất cả các toán tử số học được hỗ trợ bởi ngôn ngữ Go. Giả sử biếnA giữ 10 và biến B giữ 20 sau đó -

Hiển thị các ví dụ

Nhà điều hành Sự miêu tả Thí dụ
+ Thêm hai toán hạng A + B cho 30
- Trừ toán hạng thứ hai với toán hạng đầu tiên A - B cho -10
* Nhân cả hai toán hạng A * B cho 200
/ Chia tử số cho mẫu số. B / A cho 2
% Toán tử mô đun; cho phần còn lại sau một phép chia số nguyên. B% A cho 0
++ Toán tử tăng dần. Nó làm tăng giá trị số nguyên lên một. A ++ cho 11
- Toán tử giảm dần. Nó làm giảm giá trị số nguyên đi một. A-- cho 9

Toán tử quan hệ

Bảng sau liệt kê tất cả các toán tử quan hệ được hỗ trợ bởi ngôn ngữ Go. Giả sử biếnA giữ 10 và biến B giữ 20, sau đó -

Hiển thị các ví dụ

Nhà điều hành Sự miêu tả Thí dụ
== Nó kiểm tra xem giá trị của hai toán hạng có bằng nhau hay không; nếu có, điều kiện trở thành true. (A == B) không đúng.
! = Nó kiểm tra xem giá trị của hai toán hạng có bằng nhau hay không; nếu các giá trị không bằng nhau, thì điều kiện trở thành true. (A! = B) là đúng.
> Nó kiểm tra xem giá trị của toán hạng bên trái có lớn hơn giá trị của toán hạng bên phải hay không; nếu có, điều kiện trở thành true. (A> B) là không đúng.
< Nó kiểm tra nếu giá trị của toán hạng bên trái nhỏ hơn giá trị của toán hạng bên phải; nếu có, điều kiện trở thành true. (A <B) là đúng.
> = Nó kiểm tra nếu giá trị của toán hạng bên trái lớn hơn hoặc bằng giá trị của toán hạng bên phải; nếu có, điều kiện trở thành true. (A> = B) là không đúng.
<= Nó kiểm tra nếu giá trị của toán hạng bên trái nhỏ hơn hoặc bằng giá trị của toán hạng bên phải; nếu có, điều kiện trở thành true. (A <= B) là đúng.

Toán tử logic

Bảng sau liệt kê tất cả các toán tử logic được hỗ trợ bởi ngôn ngữ Go. Giả sử biếnA giữ 1 và biến B giữ 0, sau đó -

Hiển thị các ví dụ

Nhà điều hành Sự miêu tả Thí dụ
&& Được gọi là toán tử logic AND. Nếu cả hai toán hạng đều khác 0, thì điều kiện trở thành true. (A && B) là sai.
|| Được gọi là Toán tử logic HOẶC. Nếu bất kỳ toán hạng nào trong hai toán hạng khác 0, thì điều kiện trở thành true. (A || B) là đúng.
! Được gọi là Toán tử logic NOT. Sử dụng để đảo ngược trạng thái logic của toán hạng của nó. Nếu một điều kiện là đúng thì toán tử logic NOT sẽ sai. ! (A && B) là đúng.

Bảng sau đây cho thấy tất cả các toán tử logic được hỗ trợ bởi ngôn ngữ Go. Giả sử biếnA giữ đúng và biến B giữ sai, sau đó -

Nhà điều hành Sự miêu tả Thí dụ
&& Được gọi là toán tử logic AND. Nếu cả hai toán hạng đều sai, thì điều kiện trở thành sai. (A && B) là sai.
|| Được gọi là Toán tử logic HOẶC. Nếu bất kỳ toán hạng nào trong hai toán hạng là true thì điều kiện trở thành true. (A || B) là đúng.
! Được gọi là Toán tử logic NOT. Sử dụng để đảo ngược trạng thái logic của toán hạng của nó. Nếu một điều kiện là đúng, thì toán tử logic NOT sẽ làm cho nó sai. ! (A && B) là đúng.

Toán tử Bitwise

Toán tử bitwise làm việc trên các bit và thực hiện hoạt động từng bit. Bảng sự thật cho &, |, và ^ như sau:

p q p & q p | q p ^ q
0 0 0 0 0
0 1 0 1 1
1 1 1 1 0
1 0 0 1 1

Giả sử A = 60; và B = 13. Ở định dạng nhị phân, chúng sẽ như sau:

A = 0011 1100

B = 0000 1101

-----------------

A&B = 0000 1100

A | B = 0011 1101

A ^ B = 0011 0001

~ A = 1100 0011

Các toán tử Bitwise được ngôn ngữ C hỗ trợ được liệt kê trong bảng sau. Giả sử biến A giữ 60 và biến B giữ 13, thì -

Hiển thị các ví dụ

Nhà điều hành Sự miêu tả Thí dụ
& Toán tử AND nhị phân sao chép một bit vào kết quả nếu nó tồn tại trong cả hai toán hạng. (A & B) sẽ cho 12, là 0000 1100
| Toán tử OR nhị phân sao chép một bit nếu nó tồn tại trong một trong hai toán hạng. (A | B) sẽ cho 61, là 0011 1101
^ Toán tử XOR nhị phân sao chép bit nếu nó được đặt trong một toán hạng nhưng không phải cả hai. (A ^ B) sẽ cho 49, là 0011 0001
<< Toán tử dịch chuyển trái nhị phân. Giá trị toán hạng bên trái được di chuyển sang trái bằng số bit được chỉ định bởi toán hạng bên phải. A << 2 sẽ cho 240 là 1111 0000
>> Toán tử Shift phải nhị phân. Giá trị của toán hạng bên trái được di chuyển sang phải bằng số bit được chỉ định bởi toán hạng bên phải. A >> 2 sẽ cho 15 là 0000 1111

Người điều hành nhiệm vụ

Bảng sau liệt kê tất cả các toán tử gán được hỗ trợ bởi ngôn ngữ Go:

Hiển thị các ví dụ

Nhà điều hành Sự miêu tả Thí dụ
= Toán tử gán đơn giản, Gán giá trị từ toán hạng bên phải sang toán hạng bên trái C = A + B sẽ gán giá trị của A + B vào C
+ = Thêm toán tử gán AND, Nó thêm toán hạng bên phải vào toán hạng bên trái và gán kết quả cho toán hạng bên trái C + = A tương đương với C = C + A
- = Trừ toán tử gán AND, Nó trừ toán hạng bên phải khỏi toán hạng bên trái và gán kết quả cho toán hạng bên trái C - = A tương đương với C = C - A
* = Nhân toán tử gán AND, Nó nhân toán hạng phải với toán hạng trái và gán kết quả cho toán hạng trái C * = A tương đương với C = C * A
/ = Toán tử gán AND, Nó chia toán hạng bên trái với toán hạng bên phải và gán kết quả cho toán hạng bên trái C / = A tương đương với C = C / A
% = Toán tử gán mô-đun AND, cần mô-đun sử dụng hai toán hạng và gán kết quả cho toán hạng bên trái C% = A tương đương với C = C% A
<< = Dịch chuyển trái và toán tử gán C << = 2 giống với C = C << 2
>> = Toán tử chuyển nhượng AND phải C >> = 2 giống với C = C >> 2
& = Toán tử gán bitwise AND C & = 2 giống C = C & 2
^ = OR độc quyền bit và toán tử gán C ^ = 2 giống với C = C ^ 2
| = bao gồm bitwise OR và toán tử gán C | = 2 tương tự như C = C | 2

Các nhà khai thác khác

Có một số toán tử quan trọng khác được Go Language hỗ trợ bao gồm sizeof?:.

Hiển thị các ví dụ

Nhà điều hành Sự miêu tả Thí dụ
& Trả về địa chỉ của một biến. & a; cung cấp địa chỉ thực của biến.
* Con trỏ đến một biến. * a; cung cấp con trỏ tới một biến.

Nhà điều hành ưu tiên trong Go

Mức độ ưu tiên của toán tử xác định nhóm các từ trong một biểu thức. Điều này ảnh hưởng đến cách một biểu thức được đánh giá. Các toán tử nhất định có quyền ưu tiên cao hơn những toán tử khác; ví dụ, toán tử nhân có quyền ưu tiên cao hơn toán tử cộng.

Ví dụ x = 7 + 3 * 2; ở đây, x được gán 13, không phải 20 vì toán tử * có mức độ ưu tiên cao hơn +, vì vậy đầu tiên nó được nhân với 3 * 2 và sau đó cộng thành 7.

Ở đây, các toán tử có mức độ ưu tiên cao nhất xuất hiện ở đầu bảng, những toán tử có mức độ ưu tiên thấp nhất xuất hiện ở cuối bảng. Trong một biểu thức, các toán tử có mức độ ưu tiên cao hơn sẽ được đánh giá đầu tiên.

Hiển thị các ví dụ

thể loại Nhà điều hành Sự liên kết
Postfix () [] ->. ++ - - Trái sang phải
Một ngôi + -! ~ ++ - - (type) * & sizeof Phải sang trái
Phép nhân * /% Trái sang phải
Phụ gia + - Trái sang phải
Shift << >> Trái sang phải
Quan hệ <<=>> = Trái sang phải
Bình đẳng ==! = Trái sang phải
Bitwise VÀ & Trái sang phải
Bitwise XOR ^ Trái sang phải
Bitwise HOẶC | Trái sang phải
Logic AND && Trái sang phải
Logic HOẶC || Trái sang phải
Chuyển nhượng = + = - = * = / =% = >> = << = & = ^ = | = Phải sang trái
Dấu phẩy , Trái sang phải

Cấu trúc ra quyết định yêu cầu người lập trình chỉ định một hoặc nhiều điều kiện để được đánh giá hoặc kiểm tra bởi chương trình, cùng với một câu lệnh hoặc các câu lệnh sẽ được thực thi nếu điều kiện đó được xác định là đúng và tùy chọn, các câu lệnh khác được thực thi nếu điều kiện được xác định là sai.

Sau đây là dạng chung của cấu trúc ra quyết định điển hình được tìm thấy trong hầu hết các ngôn ngữ lập trình:

Ngôn ngữ lập trình Go cung cấp các loại câu lệnh ra quyết định sau. Nhấp vào các liên kết sau để kiểm tra chi tiết của chúng.

Sr.No Tuyên bố & Mô tả
1 câu lệnh if

An if statement bao gồm một biểu thức boolean theo sau bởi một hoặc nhiều câu lệnh.

2 câu lệnh if ... else

An if statement có thể được theo sau bởi một tùy chọn else statement, thực thi khi biểu thức boolean sai.

3 câu lệnh if lồng nhau

Bạn có thể sử dụng một if hoặc là else if tuyên bố bên trong khác if hoặc là else if các câu lệnh).

4 chuyển đổi tuyên bố

A switch câu lệnh cho phép một biến được kiểm tra tính bình đẳng với một danh sách các giá trị.

5 chọn tuyên bố

A select tuyên bố tương tự như switch tuyên bố với sự khác biệt rằng câu lệnh trường hợp đề cập đến giao tiếp kênh.

Có thể có một tình huống, khi bạn cần thực thi một khối mã nhiều lần. Nói chung, các câu lệnh được thực hiện tuần tự: Câu lệnh đầu tiên trong một hàm được thực hiện đầu tiên, tiếp theo là câu lệnh thứ hai, v.v.

Các ngôn ngữ lập trình cung cấp các cấu trúc điều khiển khác nhau cho phép các đường dẫn thực thi phức tạp hơn.

Câu lệnh lặp cho phép chúng ta thực hiện một câu lệnh hoặc một nhóm câu lệnh nhiều lần và sau đây là dạng chung của câu lệnh lặp trong hầu hết các ngôn ngữ lập trình:

Ngôn ngữ lập trình Go cung cấp các loại vòng lặp sau để xử lý các yêu cầu lặp.

Sr.No Loại vòng lặp & Mô tả
1 vòng lặp for

Nó thực hiện một chuỗi các câu lệnh nhiều lần và viết tắt mã quản lý biến vòng lặp.

2 vòng lồng nhau

Đây là một hoặc nhiều vòng lặp bên trong bất kỳ vòng lặp for nào.

Tuyên bố kiểm soát vòng lặp

Các câu lệnh điều khiển vòng lặp thay đổi một thực thi từ trình tự bình thường của nó. Khi một thực thi rời khỏi phạm vi của nó, tất cả các đối tượng tự động được tạo trong phạm vi đó sẽ bị phá hủy.

Go hỗ trợ các câu lệnh điều khiển sau:

Sr.No Tuyên bố & Mô tả Kiểm soát
1 tuyên bố ngắt

Nó chấm dứt một for loop hoặc là switch và chuyển việc thực thi đến câu lệnh ngay sau vòng lặp for hoặc chuyển đổi.

2 tiếp tục tuyên bố

Nó làm cho vòng lặp bỏ qua phần còn lại của phần thân và ngay lập tức kiểm tra lại tình trạng của nó trước khi nhắc lại.

3 tuyên bố goto

Nó chuyển quyền kiểm soát cho câu lệnh được gắn nhãn.

Vòng lặp vô hạn

Một vòng lặp trở thành một vòng lặp vô hạn nếu điều kiện của nó không bao giờ trở thành sai. Vòng lặp for thường được sử dụng cho mục đích này. Vì không có biểu thức nào trong ba biểu thức tạo thành vòng lặp for được yêu cầu, bạn có thể tạo một vòng lặp vô tận bằng cách để trống biểu thức điều kiện hoặc bằng cách chuyển true cho nó.

package main

import "fmt"

func main() {
   for true  {
       fmt.Printf("This loop will run forever.\n");
   }
}

Khi biểu thức điều kiện vắng mặt, nó được giả định là đúng. Bạn có thể có một biểu thức khởi tạo và tăng dần, nhưng các lập trình viên C thường sử dụng cấu trúc for (;;) để biểu thị một vòng lặp vô hạn.

Note - Bạn có thể kết thúc một vòng lặp vô hạn bằng cách nhấn các phím Ctrl + C.

Hàm là một nhóm các câu lệnh cùng thực hiện một tác vụ. Mỗi chương trình cờ vây đều có ít nhất một chức năng, đó làmain(). Bạn có thể chia mã của mình thành các chức năng riêng biệt. Cách bạn phân chia mã giữa các chức năng khác nhau là tùy thuộc vào bạn, nhưng về mặt logic, việc phân chia phải sao cho mỗi chức năng thực hiện một nhiệm vụ cụ thể.

Một chức năng declarationcho trình biên dịch biết về tên hàm, kiểu trả về và các tham số. Một chức năngdefinition cung cấp phần thân thực tế của hàm.

Thư viện chuẩn Go cung cấp nhiều hàm tích hợp sẵn mà chương trình của bạn có thể gọi. Ví dụ, hàmlen()nhận các đối số của nhiều kiểu khác nhau và trả về độ dài của kiểu. Nếu một chuỗi được chuyển cho nó, hàm trả về độ dài của chuỗi đó tính bằng byte. Nếu một mảng được chuyển cho nó, hàm sẽ trả về độ dài của mảng.

Các hàm còn được gọi là method, sub-routine, hoặc là procedure.

Xác định một chức năng

Dạng tổng quát của định nghĩa hàm trong ngôn ngữ lập trình Go như sau:

func function_name( [parameter list] ) [return_types]
{
   body of the function
}

Định nghĩa hàm trong ngôn ngữ lập trình Go bao gồm tiêu đề hàmthân hàm . Đây là tất cả các phần của một hàm -

  • Func - Nó bắt đầu khai báo một hàm.

  • Function Name- Đó là tên thực tế của hàm. Tên hàm và danh sách tham số cùng nhau tạo thành chữ ký hàm.

  • Parameters- Một tham số giống như một trình giữ chỗ. Khi một hàm được gọi, bạn truyền một giá trị cho tham số. Giá trị này được gọi là tham số hoặc đối số thực tế. Danh sách tham số đề cập đến kiểu, thứ tự và số lượng các tham số của một hàm. Các thông số là tùy chọn; nghĩa là, một hàm có thể không chứa tham số.

  • Return Type- Một hàm có thể trả về một danh sách các giá trị. Return_types là danh sách các kiểu dữ liệu của các giá trị mà hàm trả về. Một số hàm thực hiện các hoạt động mong muốn mà không trả về giá trị. Trong trường hợp này, return_type là không bắt buộc.

  • Function Body - Nó chứa một tập hợp các câu lệnh xác định chức năng làm gì.

Thí dụ

Mã nguồn sau đây hiển thị một hàm được gọi là max(). Hàm này nhận hai tham số num1 và num2 và trả về giá trị tối đa giữa hai tham số:

/* function returning the max between two numbers */
func max(num1, num2 int) int {
   /* local variable declaration */
   result int

   if (num1 > num2) {
      result = num1
   } else {
      result = num2
   }
   return result 
}

Gọi một hàm

Trong khi tạo một hàm Go, bạn đưa ra định nghĩa về những gì hàm phải làm. Để sử dụng một hàm, bạn sẽ phải gọi hàm đó để thực hiện tác vụ đã xác định.

Khi một chương trình gọi một chức năng, điều khiển chương trình được chuyển đến chức năng được gọi. Một hàm được gọi thực hiện một tác vụ được xác định và khi câu lệnh trả về của nó được thực thi hoặc khi đạt đến dấu ngoặc nhọn kết thúc hàm, nó sẽ trả lại điều khiển chương trình trở lại chương trình chính.

Để gọi một hàm, bạn chỉ cần chuyển các tham số cần thiết cùng với tên hàm của nó. Nếu hàm trả về một giá trị, thì bạn có thể lưu trữ giá trị trả về. Ví dụ -

package main

import "fmt"

func main() {
   /* local variable definition */
   var a int = 100
   var b int = 200
   var ret int

   /* calling a function to get max value */
   ret = max(a, b)

   fmt.Printf( "Max value is : %d\n", ret )
}

/* function returning the max between two numbers */
func max(num1, num2 int) int {
   /* local variable declaration */
   var result int

   if (num1 > num2) {
      result = num1
   } else {
      result = num2
   }
   return result 
}

Chúng tôi đã giữ hàm max () cùng với hàm main () và biên dịch mã nguồn. Trong khi chạy tệp thực thi cuối cùng, nó sẽ tạo ra kết quả sau:

Max value is : 200

Trả về nhiều giá trị từ Hàm

Một hàm Go có thể trả về nhiều giá trị. Ví dụ -

package main

import "fmt"

func swap(x, y string) (string, string) {
   return y, x
}
func main() {
   a, b := swap("Mahesh", "Kumar")
   fmt.Println(a, b)
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

Kumar Mahesh

Đối số hàm

Nếu một hàm sử dụng các đối số, nó phải khai báo các biến chấp nhận giá trị của các đối số. Các biến này được gọi làformal parameters của hàm.

Các tham số chính thức hoạt động giống như các biến cục bộ khác bên trong hàm và được tạo khi nhập vào hàm và bị hủy khi thoát.

Trong khi gọi một hàm, có hai cách mà các đối số có thể được truyền cho một hàm:

Sr.No Loại & Mô tả Cuộc gọi
1 Gọi theo giá trị

Phương thức này sao chép giá trị thực của một đối số vào tham số chính thức của hàm. Trong trường hợp này, các thay đổi được thực hiện đối với tham số bên trong hàm không ảnh hưởng đến đối số.

2 Gọi bằng cách tham khảo

Phương thức này sao chép địa chỉ của một đối số vào tham số chính thức. Bên trong hàm, địa chỉ được sử dụng để truy cập đối số thực được sử dụng trong lệnh gọi. Điều này có nghĩa là các thay đổi được thực hiện đối với tham số sẽ ảnh hưởng đến đối số.

Theo mặc định, Go sử dụng lệnh gọi theo giá trị để chuyển đối số. Nói chung, nó có nghĩa là mã bên trong một hàm không thể thay đổi các đối số được sử dụng để gọi hàm. Chương trình trên, trong khi gọi hàm max (), đã sử dụng cùng một phương thức.

Sử dụng chức năng

Một hàm có thể được sử dụng theo những cách sau:

Sr.No Sử dụng & Mô tả chức năng
1 Chức năng như giá trị

Các hàm có thể được tạo nhanh chóng và có thể được sử dụng làm giá trị.

2 Chức năng đóng cửa

Các hàm bao đóng là các hàm ẩn danh và có thể được sử dụng trong lập trình động.

3 phương pháp

Các phương thức là các chức năng đặc biệt với bộ thu.

Phạm vi trong bất kỳ chương trình nào là một vùng của chương trình nơi một biến xác định có thể tồn tại và xa hơn nữa, biến đó không thể được truy cập. Có ba nơi mà các biến có thể được khai báo trong ngôn ngữ lập trình Go:

  • Bên trong một hàm hoặc một khối (local biến)

  • Ngoài tất cả các chức năng (global biến)

  • Trong định nghĩa của tham số hàm (formal thông số)

Hãy để chúng tôi tìm hiểu những gì localglobal biến và những gì là formal thông số.

Biến cục bộ

Các biến được khai báo bên trong một hàm hoặc một khối được gọi là các biến cục bộ. Chúng chỉ có thể được sử dụng bởi các câu lệnh bên trong hàm hoặc khối mã đó. Các biến cục bộ không được biết đến với các hàm bên ngoài của chúng. Ví dụ sau sử dụng các biến cục bộ. Ở đây tất cả các biến a, b và c là cục bộ của hàm main ().

package main

import "fmt"

func main() {
   /* local variable declaration */
   var a, b, c int 

   /* actual initialization */
   a = 10
   b = 20
   c = a + b

   fmt.Printf ("value of a = %d, b = %d and c = %d\n", a, b, c)
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

value of a = 10, b = 20 and c = 30

Biến toàn cục

Các biến toàn cục được định nghĩa bên ngoài một hàm, thường nằm trên đầu chương trình. Các biến toàn cục giữ giá trị của chúng trong suốt thời gian tồn tại của chương trình và chúng có thể được truy cập bên trong bất kỳ hàm nào được định nghĩa cho chương trình.

Một biến toàn cục có thể được truy cập bởi bất kỳ hàm nào. Có nghĩa là, một biến toàn cục có sẵn để sử dụng trong suốt chương trình sau khi khai báo. Ví dụ sau sử dụng cả biến cục bộ và toàn cục:

package main

import "fmt"
 
/* global variable declaration */
var g int
 
func main() {
   /* local variable declaration */
   var a, b int

   /* actual initialization */
   a = 10
   b = 20
   g = a + b

   fmt.Printf("value of a = %d, b = %d and g = %d\n", a, b, g)
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

value of a = 10, b = 20 and g = 30

Một chương trình có thể có cùng tên cho các biến cục bộ và toàn cục nhưng giá trị của biến cục bộ bên trong một hàm được ưu tiên. Ví dụ -

package main

import "fmt"
 
/* global variable declaration */
var g int = 20
 
func main() {
   /* local variable declaration */
   var g int = 10
 
   fmt.Printf ("value of g = %d\n",  g)
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

value of g = 10

Thông số chính thức

Các tham số chính thức được coi là các biến cục bộ có trong hàm đó và chúng được ưu tiên hơn các biến toàn cục. Ví dụ -

package main

import "fmt"
 
/* global variable declaration */
var a int = 20;
 
func main() {
   /* local variable declaration in main function */
   var a int = 10
   var b int = 20
   var c int = 0

   fmt.Printf("value of a in main() = %d\n",  a);
   c = sum( a, b);
   fmt.Printf("value of c in main() = %d\n",  c);
}
/* function to add two integers */
func sum(a, b int) int {
   fmt.Printf("value of a in sum() = %d\n",  a);
   fmt.Printf("value of b in sum() = %d\n",  b);

   return a + b;
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

value of a in main() = 10
value of a in sum() = 10
value of b in sum() = 20
value of c in main() = 30

Khởi tạo các biến cục bộ và toàn cục

Các biến cục bộ và toàn cục được khởi tạo thành giá trị mặc định của chúng, là 0; trong khi con trỏ được khởi tạo thành nil.

Loại dữ liệu Giá trị mặc định ban đầu
int 0
float32 0
con trỏ không

Chuỗi, được sử dụng rộng rãi trong lập trình cờ vây, là một phần byte chỉ đọc. Trong ngôn ngữ lập trình Go, các chuỗi làslices. Nền tảng Go cung cấp các thư viện khác nhau để thao tác các chuỗi.

  • unicode
  • regexp
  • strings

Tạo chuỗi

Cách trực tiếp nhất để tạo một chuỗi là viết:

var greeting = "Hello world!"

Bất cứ khi nào nó gặp một chuỗi ký tự trong mã của bạn, trình biên dịch sẽ tạo một đối tượng chuỗi với giá trị của nó trong trường hợp này, "Hello world!".

Một chuỗi ký tự chứa một chuỗi UTF-8 hợp lệ được gọi là rune. Một chuỗi chứa các byte tùy ý.

package main

import "fmt"

func main() {
   var greeting =  "Hello world!"
   
   fmt.Printf("normal string: ")
   fmt.Printf("%s", greeting)
   fmt.Printf("\n")
   fmt.Printf("hex bytes: ")
   
   for i := 0; i < len(greeting); i++ {
       fmt.Printf("%x ", greeting[i])
   }
   fmt.Printf("\n")
   
   const sampleText = "\xbd\xb2\x3d\xbc\x20\xe2\x8c\x98" 
   /*q flag escapes unprintable characters, with + flag it escapses non-ascii 
   characters as well to make output unambigous  
   */
   fmt.Printf("quoted string: ")
   fmt.Printf("%+q", sampleText)
   fmt.Printf("\n")  
}

Điều này sẽ tạo ra kết quả sau:

normal string: Hello world!
hex bytes: 48 65 6c 6c 6f 20 77 6f 72 6c 64 21 
quoted string: "\xbd\xb2=\xbc \u2318"

Note - Chuỗi ký tự là không thay đổi, vì vậy một khi nó được tạo ra, một ký tự chuỗi không thể thay đổi.

Chiều dài chuỗi

Phương thức len (str) trả về số byte có trong chuỗi ký tự.

package main

import "fmt"

func main() {
   var greeting =  "Hello world!"
   
   fmt.Printf("String Length is: ")
   fmt.Println(len(greeting))  
}

Điều này sẽ tạo ra kết quả sau:

String Length is : 12

Nối các chuỗi

Gói chuỗi bao gồm một phương thức join để nối nhiều chuỗi -

strings.Join(sample, " ")

Tham gia nối các phần tử của một mảng để tạo một chuỗi duy nhất. Tham số thứ hai là seperator được đặt giữa phần tử của mảng.

Chúng ta hãy xem ví dụ sau:

package main

import ("fmt" "math" )"fmt" "strings")

func main() {
   greetings :=  []string{"Hello","world!"}   
   fmt.Println(strings.Join(greetings, " "))
}

Điều này sẽ tạo ra kết quả sau:

Hello world!

Ngôn ngữ lập trình Go cung cấp một cấu trúc dữ liệu được gọi là the array, có thể lưu trữ tập hợp tuần tự có kích thước cố định của các phần tử cùng loại. Mảng được sử dụng để lưu trữ một tập hợp dữ liệu, nhưng thường hữu ích hơn nếu coi một mảng là một tập hợp các biến cùng kiểu.

Thay vì khai báo các biến riêng lẻ, chẳng hạn như number0, number1, ... và number99, bạn khai báo một biến mảng chẳng hạn như số và sử dụng số [0], số [1] và ..., số [99] để biểu diễn các biến riêng lẻ. Một phần tử cụ thể trong một mảng được truy cập bởi một chỉ mục.

Tất cả các mảng bao gồm các vị trí bộ nhớ liền nhau. Địa chỉ thấp nhất tương ứng với phần tử đầu tiên và địa chỉ cao nhất cho phần tử cuối cùng.

Khai báo Mảng

Để khai báo một mảng trong Go, một lập trình viên chỉ định kiểu của các phần tử và số phần tử theo yêu cầu của một mảng như sau:

var variable_name [SIZE] variable_type

Đây được gọi là mảng một chiều . CácarraySize phải là một hằng số nguyên lớn hơn 0 và typecó thể là bất kỳ kiểu dữ liệu Go hợp lệ nào. Ví dụ, để khai báo một mảng 10 phần tử được gọi làbalance kiểu float32, hãy sử dụng câu lệnh này -

var balance [10] float32

Đây, balance là một mảng biến có thể chứa tối đa 10 số thực.

Khởi tạo Mảng

Bạn có thể khởi tạo mảng trong Go từng cái một hoặc sử dụng một câu lệnh như sau:

var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

Số lượng giá trị giữa các dấu ngoặc vuông {} không được lớn hơn số phần tử mà chúng ta khai báo cho mảng giữa các dấu ngoặc vuông [].

Nếu bạn bỏ qua kích thước của mảng, một mảng vừa đủ lớn để chứa quá trình khởi tạo sẽ được tạo. Do đó, nếu bạn viết -

var balance = []float32{1000.0, 2.0, 3.4, 7.0, 50.0}

Bạn sẽ tạo chính xác mảng giống như bạn đã làm trong ví dụ trước. Sau đây là một ví dụ để gán một phần tử duy nhất của mảng:

balance[4] = 50.0

Các chuyển nhượng tuyên bố số lượng phần tử 5 trên thứ trong mảng với giá trị là 50,0. Tất cả các mảng có 0 là chỉ số của phần tử đầu tiên của chúng, còn được gọi là chỉ số cơ sở và chỉ số cuối cùng của một mảng sẽ là tổng kích thước của mảng trừ đi 1. Sau đây là biểu diễn bằng hình ảnh của cùng một mảng mà chúng ta đã thảo luận ở trên:

Truy cập các phần tử mảng

Một phần tử được truy cập bằng cách đánh chỉ mục tên mảng. Điều này được thực hiện bằng cách đặt chỉ mục của phần tử trong dấu ngoặc vuông sau tên của mảng. Ví dụ -

float32 salary = balance[9]

Câu lệnh trên sẽ lấy phần tử thứ 10 từ mảng và gán giá trị cho biến lương. Sau đây là một ví dụ sẽ sử dụng tất cả ba khái niệm đã đề cập ở trên viz. khai báo, gán và truy cập mảng -

package main

import "fmt"

func main() {
   var n [10]int /* n is an array of 10 integers */
   var i,j int

   /* initialize elements of array n to 0 */         
   for i = 0; i < 10; i++ {
      n[i] = i + 100 /* set element at location i to i + 100 */
   }
   /* output each array element's value */
   for j = 0; j < 10; j++ {
      fmt.Printf("Element[%d] = %d\n", j, n[j] )
   }
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

Element[0] = 100
Element[1] = 101
Element[2] = 102
Element[3] = 103
Element[4] = 104
Element[5] = 105
Element[6] = 106
Element[7] = 107
Element[8] = 108
Element[9] = 109

Xem chi tiết các mảng

Có những khái niệm quan trọng liên quan đến mảng mà một lập trình viên Go phải rõ ràng -

Sr.No Khái niệm & Mô tả
1 Mảng đa chiều

Go hỗ trợ mảng đa chiều. Dạng đơn giản nhất của mảng nhiều chiều là mảng hai chiều.

2 Truyền mảng cho các hàm

Bạn có thể chuyển cho hàm một con trỏ tới một mảng bằng cách chỉ định tên của mảng mà không có chỉ mục.

Con trỏ trong cờ vây rất dễ học và thú vị. Một số tác vụ lập trình cờ vây được thực hiện dễ dàng hơn với con trỏ và các tác vụ khác, chẳng hạn như gọi bằng tham chiếu, không thể thực hiện nếu không sử dụng con trỏ. Vì vậy, nó trở nên cần thiết để học các mẹo để trở thành một lập trình viên cờ vây hoàn hảo.

Như bạn đã biết, mọi biến là một vị trí bộ nhớ và mọi vị trí bộ nhớ đều có địa chỉ của nó được xác định có thể được truy cập bằng cách sử dụng toán tử dấu và (&), biểu thị một địa chỉ trong bộ nhớ. Hãy xem xét ví dụ sau, ví dụ này sẽ in ra địa chỉ của các biến được xác định:

package main

import "fmt"

func main() {
   var a int = 10   
   fmt.Printf("Address of a variable: %x\n", &a  )
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

Address of a variable: 10328000

Như vậy bạn đã hiểu địa chỉ bộ nhớ là gì và cách truy cập nó. Bây giờ chúng ta hãy xem các con trỏ là gì.

Con trỏ là gì?

A pointerlà một biến có giá trị là địa chỉ của một biến khác, tức là địa chỉ trực tiếp của vị trí bộ nhớ. Giống như bất kỳ biến hoặc hằng số nào, bạn phải khai báo một con trỏ trước khi có thể sử dụng nó để lưu trữ bất kỳ địa chỉ biến nào. Dạng chung của khai báo biến con trỏ là:

var var_name *var-type

Đây, typelà kiểu cơ sở của con trỏ; nó phải là kiểu dữ liệu C hợp lệ vàvar-namelà tên của biến con trỏ. Dấu hoa thị * mà bạn sử dụng để khai báo một con trỏ giống với dấu hoa thị mà bạn sử dụng cho phép nhân. Tuy nhiên, trong câu lệnh này, dấu hoa thị được sử dụng để chỉ định một biến làm con trỏ. Sau đây là khai báo con trỏ hợp lệ:

var ip *int        /* pointer to an integer */
var fp *float32    /* pointer to a float */

Kiểu dữ liệu thực tế của giá trị của tất cả các con trỏ, dù là số nguyên, số thực hay cách khác, đều giống nhau, một số thập lục phân dài đại diện cho địa chỉ bộ nhớ. Sự khác biệt duy nhất giữa các con trỏ của các kiểu dữ liệu khác nhau là kiểu dữ liệu của biến hoặc hằng số mà con trỏ trỏ tới.

Làm thế nào để sử dụng con trỏ?

Có một vài thao tác quan trọng mà chúng tôi thường thực hiện với con trỏ: (a) chúng tôi xác định biến con trỏ, (b) gán địa chỉ của một biến cho con trỏ và (c) truy cập giá trị tại địa chỉ được lưu trữ trong biến con trỏ .

Tất cả các hoạt động này được thực hiện bằng cách sử dụng toán tử một ngôi * trả về giá trị của biến nằm tại địa chỉ được chỉ định bởi toán hạng của nó. Ví dụ sau minh họa cách thực hiện các thao tác này:

package main

import "fmt"

func main() {
   var a int = 20   /* actual variable declaration */
   var ip *int      /* pointer variable declaration */

   ip = &a  /* store address of a in pointer variable*/

   fmt.Printf("Address of a variable: %x\n", &a  )

   /* address stored in pointer variable */
   fmt.Printf("Address stored in ip variable: %x\n", ip )

   /* access the value using the pointer */
   fmt.Printf("Value of *ip variable: %d\n", *ip )
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

Address of var variable: 10328000
Address stored in ip variable: 10328000
Value of *ip variable: 20

Nil Pointers in Go

Trình biên dịch Go gán giá trị Nil cho một biến con trỏ trong trường hợp bạn không có địa chỉ chính xác để được gán. Điều này được thực hiện tại thời điểm khai báo biến. Một con trỏ được gán nil được gọi lànil con trỏ.

Con trỏ nil là một hằng số có giá trị bằng 0 được xác định trong một số thư viện chuẩn. Hãy xem xét chương trình sau:

package main

import "fmt"

func main() {
   var  ptr *int

   fmt.Printf("The value of ptr is : %x\n", ptr  )
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

The value of ptr is 0

Trên hầu hết các hệ điều hành, các chương trình không được phép truy cập bộ nhớ ở địa chỉ 0 vì bộ nhớ đó được hệ điều hành dành riêng. Tuy nhiên, địa chỉ bộ nhớ 0 có ý nghĩa đặc biệt; nó báo hiệu rằng con trỏ không nhằm mục đích trỏ đến vị trí bộ nhớ có thể truy cập được. Nhưng theo quy ước, nếu một con trỏ chứa giá trị nil (không), nó được coi là không trỏ đến.

Để kiểm tra con trỏ nil, bạn có thể sử dụng câu lệnh if như sau:

if(ptr != nil)     /* succeeds if p is not nil */
if(ptr == nil)    /* succeeds if p is null */

Xem chi tiết con trỏ

Con trỏ có nhiều khái niệm nhưng dễ và chúng rất quan trọng đối với lập trình cờ vây. Các khái niệm sau về con trỏ phải rõ ràng đối với một lập trình viên cờ vây:

Sr.No Khái niệm & Mô tả
1 Go - Mảng con trỏ

Bạn có thể xác định mảng để chứa một số con trỏ.

2 Đi - Con trỏ tới con trỏ

Go cho phép bạn có con trỏ trên một con trỏ, v.v.

3 Chuyển con trỏ đến các hàm trong Go

Truyền một đối số theo tham chiếu hoặc theo địa chỉ đều cho phép đối số đã truyền được thay đổi trong hàm gọi bởi hàm được gọi.

Mảng Go cho phép bạn xác định các biến có thể chứa một số mục dữ liệu cùng loại. Structure là một kiểu dữ liệu khác do người dùng xác định có sẵn trong lập trình Go, cho phép bạn kết hợp các mục dữ liệu khác nhau.

Các cấu trúc được sử dụng để biểu diễn một bản ghi. Giả sử bạn muốn theo dõi các cuốn sách trong thư viện. Bạn có thể muốn theo dõi các thuộc tính sau của mỗi cuốn sách:

  • Title
  • Author
  • Subject
  • Mã sách

Trong trường hợp như vậy, các cấu trúc rất hữu ích.

Xác định cấu trúc

Để xác định cấu trúc, bạn phải sử dụng typestructcác câu lệnh. Câu lệnh struct xác định một kiểu dữ liệu mới, với nhiều thành viên cho chương trình của bạn. Câu lệnh type liên kết tên với kiểu là struct trong trường hợp của chúng ta. Định dạng của câu lệnh struct như sau:

type struct_variable_type struct {
   member definition;
   member definition;
   ...
   member definition;
}

Khi một kiểu cấu trúc được xác định, nó có thể được sử dụng để khai báo các biến của kiểu đó bằng cú pháp sau.

variable_name := structure_variable_type {value1, value2...valuen}

Truy cập thành viên cấu trúc

Để truy cập bất kỳ thành viên nào của một cấu trúc, chúng tôi sử dụng member access operator (.).Toán tử truy cập thành viên được mã hóa là dấu chấm giữa tên biến cấu trúc và thành viên cấu trúc mà chúng ta muốn truy cập. Bạn sẽ sử dụngstructtừ khóa để xác định các biến của kiểu cấu trúc. Ví dụ sau giải thích cách sử dụng cấu trúc:

package main

import "fmt"

type Books struct {
   title string
   author string
   subject string
   book_id int
}
func main() {
   var Book1 Books    /* Declare Book1 of type Book */
   var Book2 Books    /* Declare Book2 of type Book */
 
   /* book 1 specification */
   Book1.title = "Go Programming"
   Book1.author = "Mahesh Kumar"
   Book1.subject = "Go Programming Tutorial"
   Book1.book_id = 6495407

   /* book 2 specification */
   Book2.title = "Telecom Billing"
   Book2.author = "Zara Ali"
   Book2.subject = "Telecom Billing Tutorial"
   Book2.book_id = 6495700
 
   /* print Book1 info */
   fmt.Printf( "Book 1 title : %s\n", Book1.title)
   fmt.Printf( "Book 1 author : %s\n", Book1.author)
   fmt.Printf( "Book 1 subject : %s\n", Book1.subject)
   fmt.Printf( "Book 1 book_id : %d\n", Book1.book_id)

   /* print Book2 info */
   fmt.Printf( "Book 2 title : %s\n", Book2.title)
   fmt.Printf( "Book 2 author : %s\n", Book2.author)
   fmt.Printf( "Book 2 subject : %s\n", Book2.subject)
   fmt.Printf( "Book 2 book_id : %d\n", Book2.book_id)
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

Book 1 title      : Go Programming
Book 1 author     : Mahesh Kumar
Book 1 subject    : Go Programming Tutorial
Book 1 book_id    : 6495407
Book 2 title      : Telecom Billing
Book 2 author     : Zara Ali
Book 2 subject    : Telecom Billing Tutorial
Book 2 book_id    : 6495700

Cấu trúc dưới dạng đối số hàm

Bạn có thể truyền một cấu trúc như một đối số của hàm theo cách tương tự như khi bạn truyền bất kỳ biến hoặc con trỏ nào khác. Bạn sẽ truy cập các biến cấu trúc theo cách giống như cách bạn đã làm trong ví dụ trên -

package main

import "fmt"

type Books struct {
   title string
   author string
   subject string
   book_id int
}
func main() {
   var Book1 Books    /* Declare Book1 of type Book */
   var Book2 Books    /* Declare Book2 of type Book */
 
   /* book 1 specification */
   Book1.title = "Go Programming"
   Book1.author = "Mahesh Kumar"
   Book1.subject = "Go Programming Tutorial"
   Book1.book_id = 6495407

   /* book 2 specification */
   Book2.title = "Telecom Billing"
   Book2.author = "Zara Ali"
   Book2.subject = "Telecom Billing Tutorial"
   Book2.book_id = 6495700
 
   /* print Book1 info */
   printBook(Book1)

   /* print Book2 info */
   printBook(Book2)
}
func printBook( book Books ) {
   fmt.Printf( "Book title : %s\n", book.title);
   fmt.Printf( "Book author : %s\n", book.author);
   fmt.Printf( "Book subject : %s\n", book.subject);
   fmt.Printf( "Book book_id : %d\n", book.book_id);
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

Book title     : Go Programming
Book author    : Mahesh Kumar
Book subject   : Go Programming Tutorial
Book book_id   : 6495407
Book title     : Telecom Billing
Book author    : Zara Ali
Book subject   : Telecom Billing Tutorial
Book book_id   : 6495700

Con trỏ đến cấu trúc

Bạn có thể xác định con trỏ đến cấu trúc giống như cách bạn xác định con trỏ cho bất kỳ biến nào khác như sau:

var struct_pointer *Books

Bây giờ, bạn có thể lưu trữ địa chỉ của một biến cấu trúc trong biến con trỏ đã xác định ở trên. Để tìm địa chỉ của một biến cấu trúc, hãy đặt toán tử & trước tên của cấu trúc như sau:

struct_pointer = &Book1;

Để truy cập các thành viên của một cấu trúc bằng cách sử dụng một con trỏ tới cấu trúc đó, bạn phải sử dụng dấu "." toán tử như sau -

struct_pointer.title;

Hãy để chúng tôi viết lại ví dụ trên bằng cách sử dụng con trỏ cấu trúc -

package main

import "fmt"

type Books struct {
   title string
   author string
   subject string
   book_id int
}
func main() {
   var Book1 Books   /* Declare Book1 of type Book */
   var Book2 Books   /* Declare Book2 of type Book */
 
   /* book 1 specification */
   Book1.title = "Go Programming"
   Book1.author = "Mahesh Kumar"
   Book1.subject = "Go Programming Tutorial"
   Book1.book_id = 6495407

   /* book 2 specification */
   Book2.title = "Telecom Billing"
   Book2.author = "Zara Ali"
   Book2.subject = "Telecom Billing Tutorial"
   Book2.book_id = 6495700
 
   /* print Book1 info */
   printBook(&Book1)

   /* print Book2 info */
   printBook(&Book2)
}
func printBook( book *Books ) {
   fmt.Printf( "Book title : %s\n", book.title);
   fmt.Printf( "Book author : %s\n", book.author);
   fmt.Printf( "Book subject : %s\n", book.subject);
   fmt.Printf( "Book book_id : %d\n", book.book_id);
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

Book title     : Go Programming
Book author    : Mahesh Kumar
Book subject   : Go Programming Tutorial
Book book_id   : 6495407
Book title     : Telecom Billing
Book author    : Zara Ali
Book subject   : Telecom Billing Tutorial
Book book_id   : 6495700

Go Slice là một sự trừu tượng so với Go Array. Go Array cho phép bạn xác định các biến có thể chứa một số mục dữ liệu cùng loại nhưng nó không cung cấp bất kỳ phương thức sẵn có nào để tăng kích thước của nó một cách động hoặc nhận được một mảng con của riêng nó. Slices khắc phục hạn chế này. Nó cung cấp nhiều chức năng tiện ích cần thiết trên Array và được sử dụng rộng rãi trong lập trình Go.

Xác định một lát cắt

Để xác định một lát cắt, bạn có thể khai báo nó dưới dạng một mảng mà không cần chỉ định kích thước của nó. Ngoài ra, bạn có thể sử dụngmake chức năng tạo một lát cắt.

var numbers []int /* a slice of unspecified size */
/* numbers == []int{0,0,0,0,0}*/
numbers = make([]int,5,5) /* a slice of length 5 and capacity 5*/

hàm len () và cap ()

Một lát cắt là một sự trừu tượng hóa trên mảng. Nó thực sự sử dụng mảng như một cấu trúc cơ bản. Cáclen() hàm trả về các phần tử có trong phần cap()hàm trả về dung lượng của lát cắt (tức là nó có thể chứa bao nhiêu phần tử). Ví dụ sau giải thích cách sử dụng của lát cắt -

package main

import "fmt"

func main() {
   var numbers = make([]int,3,5)
   printSlice(numbers)
}
func printSlice(x []int){
   fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

len = 3 cap = 5 slice = [0 0 0]

Nil lát

Nếu một lát cắt được khai báo không có đầu vào, thì theo mặc định, nó được khởi tạo là nil. Chiều dài và công suất của nó bằng không. Ví dụ -

package main

import "fmt"

func main() {
   var numbers []int
   printSlice(numbers)
   
   if(numbers == nil){
      fmt.Printf("slice is nil")
   }
}
func printSlice(x []int){
   fmt.Printf("len = %d cap = %d slice = %v\n", len(x), cap(x),x)
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

len = 0 cap = 0 slice = []
slice is nil

Đăng ký

Slice cho phép giới hạn dưới và giới hạn trên được chỉ định để lấy sublice của nó bằng cách sử dụng[lower-bound:upper-bound]. Ví dụ -

package main

import "fmt"

func main() {
   /* create a slice */
   numbers := []int{0,1,2,3,4,5,6,7,8}   
   printSlice(numbers)
   
   /* print the original slice */
   fmt.Println("numbers ==", numbers)
   
   /* print the sub slice starting from index 1(included) to index 4(excluded)*/
   fmt.Println("numbers[1:4] ==", numbers[1:4])
   
   /* missing lower bound implies 0*/
   fmt.Println("numbers[:3] ==", numbers[:3])
   
   /* missing upper bound implies len(s)*/
   fmt.Println("numbers[4:] ==", numbers[4:])
   
   numbers1 := make([]int,0,5)
   printSlice(numbers1)
   
   /* print the sub slice starting from index 0(included) to index 2(excluded) */
   number2 := numbers[:2]
   printSlice(number2)
   
   /* print the sub slice starting from index 2(included) to index 5(excluded) */
   number3 := numbers[2:5]
   printSlice(number3)
   
}
func printSlice(x []int){
   fmt.Printf("len = %d cap = %d slice = %v\n", len(x), cap(x),x)
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

len = 9 cap = 9 slice = [0 1 2 3 4 5 6 7 8]
numbers == [0 1 2 3 4 5 6 7 8]
numbers[1:4] == [1 2 3]
numbers[:3] == [0 1 2]
numbers[4:] == [4 5 6 7 8]
len = 0 cap = 5 slice = []
len = 2 cap = 9  slice = [0 1]
len = 3 cap = 7 slice = [2 3 4]

Hàm append () và copy ()

Người ta có thể tăng dung lượng của một lát bằng cách sử dụng append()chức năng. Sử dụngcopy(), nội dung của lát nguồn được sao chép sang lát đích. Ví dụ -

package main

import "fmt"

func main() {
   var numbers []int
   printSlice(numbers)
   
   /* append allows nil slice */
   numbers = append(numbers, 0)
   printSlice(numbers)
   
   /* add one element to slice*/
   numbers = append(numbers, 1)
   printSlice(numbers)
   
   /* add more than one element at a time*/
   numbers = append(numbers, 2,3,4)
   printSlice(numbers)
   
   /* create a slice numbers1 with double the capacity of earlier slice*/
   numbers1 := make([]int, len(numbers), (cap(numbers))*2)
   
   /* copy content of numbers to numbers1 */
   copy(numbers1,numbers)
   printSlice(numbers1)   
}
func printSlice(x []int){
   fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

len = 0 cap = 0 slice = []
len = 1 cap = 2 slice = [0]
len = 2 cap = 2 slice = [0 1]
len = 5 cap = 8 slice = [0 1 2 3 4]
len = 5 cap = 16 slice = [0 1 2 3 4]

Các range từ khóa được sử dụng trong forvòng lặp để lặp lại các mục của một mảng, lát cắt, kênh hoặc bản đồ. Với mảng và lát, nó trả về chỉ số của mục dưới dạng số nguyên. Với bản đồ, nó trả về khóa của cặp khóa-giá trị tiếp theo. Phạm vi trả về một hoặc hai giá trị. Nếu chỉ có một giá trị được sử dụng ở bên trái của biểu thức phạm vi, thì đó là giá trị đầu tiên trong bảng sau.

Biểu thức phạm vi Giá trị đầu tiên Giá trị thứ 2 (Tùy chọn)
Mảng hoặc lát cắt a [n] E chỉ mục tôi int a [i] E
String s loại chuỗi chỉ mục tôi int rune int
map m map [K] V phím k K giá trị m [k] V
kênh c chan E phần tử e E không ai

Thí dụ

Đoạn văn sau đây trình bày cách sử dụng phạm vi -

package main

import "fmt"

func main() {
   /* create a slice */
   numbers := []int{0,1,2,3,4,5,6,7,8} 
   
   /* print the numbers */
   for i:= range numbers {
      fmt.Println("Slice item",i,"is",numbers[i])
   }
   
   /* create a map*/
   countryCapitalMap := map[string] string {"France":"Paris","Italy":"Rome","Japan":"Tokyo"}
   
   /* print map using keys*/
   for country := range countryCapitalMap {
      fmt.Println("Capital of",country,"is",countryCapitalMap[country])
   }
   
   /* print map using key-value*/
   for country,capital := range countryCapitalMap {
      fmt.Println("Capital of",country,"is",capital)
   }
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

Slice item 0 is 0
Slice item 1 is 1
Slice item 2 is 2
Slice item 3 is 3
Slice item 4 is 4
Slice item 5 is 5
Slice item 6 is 6
Slice item 7 is 7
Slice item 8 is 8
Capital of France is Paris
Capital of Italy is Rome
Capital of Japan is Tokyo
Capital of France is Paris
Capital of Italy is Rome
Capital of Japan is Tokyo

Go cung cấp một kiểu dữ liệu quan trọng khác có tên là bản đồ ánh xạ các khóa duy nhất tới các giá trị. Khóa là một đối tượng mà bạn sử dụng để truy xuất giá trị vào một ngày sau đó. Với một khóa và một giá trị, bạn có thể lưu trữ giá trị trong một đối tượng Bản đồ. Sau khi giá trị được lưu trữ, bạn có thể truy xuất nó bằng cách sử dụng khóa của nó.

Xác định bản đồ

Bạn phải dùng make chức năng tạo bản đồ.

/* declare a variable, by default map will be nil*/
var map_variable map[key_data_type]value_data_type

/* define the map as nil map can not be assigned any value*/
map_variable = make(map[key_data_type]value_data_type)

Thí dụ

Ví dụ sau minh họa cách tạo và sử dụng bản đồ -

package main

import "fmt"

func main() {
   var countryCapitalMap map[string]string
   /* create a map*/
   countryCapitalMap = make(map[string]string)
   
   /* insert key-value pairs in the map*/
   countryCapitalMap["France"] = "Paris"
   countryCapitalMap["Italy"] = "Rome"
   countryCapitalMap["Japan"] = "Tokyo"
   countryCapitalMap["India"] = "New Delhi"
   
   /* print map using keys*/
   for country := range countryCapitalMap {
      fmt.Println("Capital of",country,"is",countryCapitalMap[country])
   }
   
   /* test if entry is present in the map or not*/
   capital, ok := countryCapitalMap["United States"]
   
   /* if ok is true, entry is present otherwise entry is absent*/
   if(ok){
      fmt.Println("Capital of United States is", capital)  
   } else {
      fmt.Println("Capital of United States is not present") 
   }
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

Capital of India is New Delhi
Capital of France is Paris
Capital of Italy is Rome
Capital of Japan is Tokyo
Capital of United States is not present

chức năng delete ()

Hàm delete () được sử dụng để xóa mục nhập khỏi bản đồ. Nó yêu cầu bản đồ và chìa khóa tương ứng phải được xóa. Ví dụ -

package main

import "fmt"

func main() {   
   /* create a map*/
   countryCapitalMap := map[string] string {"France":"Paris","Italy":"Rome","Japan":"Tokyo","India":"New Delhi"}
   
   fmt.Println("Original map")   
   
   /* print map */
   for country := range countryCapitalMap {
      fmt.Println("Capital of",country,"is",countryCapitalMap[country])
   }
   
   /* delete an entry */
   delete(countryCapitalMap,"France");
   fmt.Println("Entry for France is deleted")  
   
   fmt.Println("Updated map")   
   
   /* print map */
   for country := range countryCapitalMap {
      fmt.Println("Capital of",country,"is",countryCapitalMap[country])
   }
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

Original Map
Capital of France is Paris
Capital of Italy is Rome
Capital of Japan is Tokyo
Capital of India is New Delhi
Entry for France is deleted
Updated Map
Capital of India is New Delhi
Capital of Italy is Rome
Capital of Japan is Tokyo

Đệ quy là quá trình lặp lại các mục theo cách tương tự. Khái niệm tương tự cũng được áp dụng trong các ngôn ngữ lập trình. Nếu một chương trình cho phép gọi một hàm bên trong cùng một hàm, thì nó được gọi là lệnh gọi hàm đệ quy. Hãy xem ví dụ sau:

func recursion() {
   recursion() /* function calls itself */
}
func main() {
   recursion()
}

Ngôn ngữ lập trình Go hỗ trợ đệ quy. Nghĩa là, nó cho phép một hàm gọi chính nó. Nhưng trong khi sử dụng đệ quy, người lập trình cần phải cẩn thận để xác định một điều kiện thoát khỏi hàm, nếu không nó sẽ trở thành một vòng lặp vô hạn.

Ví dụ về đệ quy trong cờ vây

Các hàm đệ quy rất hữu ích để giải quyết nhiều vấn đề toán học như tính giai thừa của một số, tạo chuỗi Fibonacci, v.v.

Ví dụ 1: Tính giai thừa sử dụng đệ quy trong Go

Ví dụ sau đây tính giai thừa của một số nhất định bằng cách sử dụng một hàm đệ quy:

package main

import "fmt"

func factorial(i int)int {
   if(i <= 1) {
      return 1
   }
   return i * factorial(i - 1)
}
func main() { 
   var i int = 15
   fmt.Printf("Factorial of %d is %d", i, factorial(i))
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

Factorial of 15 is 1307674368000

Ví dụ 2: Chuỗi Fibonacci sử dụng đệ quy trong Go

Ví dụ sau đây cho thấy cách tạo chuỗi Fibonacci của một số nhất định bằng cách sử dụng một hàm đệ quy:

package main

import "fmt"

func fibonaci(i int) (ret int) {
   if i == 0 {
      return 0
   }
   if i == 1 {
      return 1
   }
   return fibonaci(i-1) + fibonaci(i-2)
}
func main() {
   var i int
   for i = 0; i < 10; i++ {
      fmt.Printf("%d ", fibonaci(i))
   }
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

0 1 1 2 3 5 8 13 21 34

Ép kiểu là một cách để chuyển đổi một biến từ kiểu dữ liệu này sang kiểu dữ liệu khác. Ví dụ: nếu bạn muốn lưu trữ một giá trị dài thành một số nguyên đơn giản thì bạn có thể nhập cast long thành int. Bạn có thể chuyển đổi các giá trị từ loại này sang loại khác bằng cách sử dụngcast operator. Cú pháp của nó như sau:

type_name(expression)

Thí dụ

Hãy xem xét ví dụ sau trong đó toán tử ép kiểu khiến phép chia một biến số nguyên cho một biến số nguyên khác được thực hiện như một phép toán số thực.

package main

import "fmt"

func main() {
   var sum int = 17
   var count int = 5
   var mean float32
   
   mean = float32(sum)/float32(count)
   fmt.Printf("Value of mean : %f\n",mean)
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

Value of mean : 3.400000

Lập trình Go cung cấp một kiểu dữ liệu khác được gọi là interfacesđại diện cho một tập hợp các chữ ký phương thức. Kiểu dữ liệu struct triển khai các giao diện này để có các định nghĩa phương thức cho chữ ký phương thức của các giao diện.

Cú pháp

/* define an interface */
type interface_name interface {
   method_name1 [return_type]
   method_name2 [return_type]
   method_name3 [return_type]
   ...
   method_namen [return_type]
}

/* define a struct */
type struct_name struct {
   /* variables */
}

/* implement interface methods*/
func (struct_name_variable struct_name) method_name1() [return_type] {
   /* method implementation */
}
...
func (struct_name_variable struct_name) method_namen() [return_type] {
   /* method implementation */
}

Thí dụ

package main

import (
   "fmt" 
   "math" 
)

/* define an interface */
type Shape interface {
   area() float64
}

/* define a circle */
type Circle struct {
   x,y,radius float64
}

/* define a rectangle */
type Rectangle struct {
   width, height float64
}

/* define a method for circle (implementation of Shape.area())*/
func(circle Circle) area() float64 {
   return math.Pi * circle.radius * circle.radius
}

/* define a method for rectangle (implementation of Shape.area())*/
func(rect Rectangle) area() float64 {
   return rect.width * rect.height
}

/* define a method for shape */
func getArea(shape Shape) float64 {
   return shape.area()
}

func main() {
   circle := Circle{x:0,y:0,radius:5}
   rectangle := Rectangle {width:10, height:5}
   
   fmt.Printf("Circle area: %f\n",getArea(circle))
   fmt.Printf("Rectangle area: %f\n",getArea(rectangle))
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

Circle area: 78.539816
Rectangle area: 50.000000

Lập trình Go cung cấp một khung xử lý lỗi khá đơn giản với kiểu giao diện lỗi có sẵn của khai báo sau:

type error interface {
   Error() string
}

Các hàm thường trả về lỗi dưới dạng giá trị trả về cuối cùng. Sử dụngerrors.New để tạo một thông báo lỗi cơ bản như sau:

func Sqrt(value float64)(float64, error) {
   if(value < 0){
      return 0, errors.New("Math: negative number passed to Sqrt")
   }
   return math.Sqrt(value), nil
}

Sử dụng giá trị trả về và thông báo lỗi.

result, err:= Sqrt(-1)

if err != nil {
   fmt.Println(err)
}

Thí dụ

package main

import "errors"
import "fmt"
import "math"

func Sqrt(value float64)(float64, error) {
   if(value < 0){
      return 0, errors.New("Math: negative number passed to Sqrt")
   }
   return math.Sqrt(value), nil
}
func main() {
   result, err:= Sqrt(-1)

   if err != nil {
      fmt.Println(err)
   } else {
      fmt.Println(result)
   }
   
   result, err = Sqrt(9)

   if err != nil {
      fmt.Println(err)
   } else {
      fmt.Println(result)
   }
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

Math: negative number passed to Sqrt
3