You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: ch1-basic/README.md
+10-3Lines changed: 10 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,8 +9,15 @@
9
9
</div>
10
10
<br/>
11
11
12
-
>*Tôi không biết tại sao bạn lại không vui trong suốt 10 năm qua. Nhưng hãy tin tôi đi, xóa bỏ đi những nặng nhọc trong quá khứ, dùng ngôn ngữ Go và trải nghiệm niềm hạnh phúc bắt đầu!*
13
-
14
-
>*Những viên gạch nhỏ được đóng góp cuối cùng sẽ xây được một lâu đài kiên cố - Xiao Zhang*
12
+
>*“Go is no Erlang, Smalltalk or Scheme, nothing pure. But it works great and is fun!” – Frank Mueller (@themue)"*
15
13
16
14
Chương này bắt đầu bằng vài lời giới thiệu về lịch sử của ngôn ngữ Go và phân tích chi tiết cuộc cách mạng của chương trình "Hello World" với những thế hệ ngôn ngữ đi trước. Sau đó, một số cấu trúc dữ liệu sẽ được trình bày như `arrays`, `strings`, và `slices`, tính chất `process-oriented` và `duck typing` được thể hiện qua `functions`, `methods`, và `interfaces`, đặc biệt là mô hình `concurrent programming` và `error handling` cũng được giới thiệu sơ qua. Cuối cùng, một số trọng tâm trong việc phát triển chương trình trên các nền tảng macOS, Windows, và Linux, cũng như một vài editor và môi trường phát triển tích hợp (IDE) cũng được đề cập, bởi vì có công cụ tốt thì năng suất làm việc mới tăng lên.
15
+
16
+
Quyển sách này được xác định là một trong những quyển sách nâng cao về Golang, vì vậy người đọc cần có một nền tảng Golang nhất định. Nếu bạn không biết nhiều về Golang, tác giả khuyên bạn nên học Golang với một số gợi ý sau.
17
+
18
+
- Sau khi cài đặt Golang và tải hướng dẫn bằng `go get golang.org/x/tour`, có thể xem hướng dẫn [A Tour of Go](https://tour.golang.org/welcome/1) ngay ở local bằng lệnh `tour`.
19
+
- Bạn cũng có thể đọc hướng dẫn ["Ngôn ngữ lập trình Go"](http://www.gopl.io/) được xuất bản bởi team Golang chính thức . ["Ngôn ngữ lập trình Go"](http://www.gopl.io/) được gọi là *Kinh thánh* Golang trong cộng đồng Golang mà bạn phải đọc thật bài bản.
20
+
21
+
Trong khi học, hãy cố gắng giải quyết một số vấn đề nhỏ với Golang. Nếu bạn muốn tham khảo API, có thể mở truy vấn tài liệu tích hợp bằng lệnh `godoc`.
22
+
23
+
Từ thời điểm này chúng ta sẽ mặc định rằng bạn có thể sử dụng Golang một cách thuần thục.
Copy file name to clipboardExpand all lines: ch1-basic/ch1-01-genesis.md
+5-5Lines changed: 5 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,7 +2,7 @@
2
2
3
3
Ngôn ngữ [Go](https://golang.org/) ban đầu được thiết kế và phát triển bởi một nhóm kĩ sư Google bao gồm **Robert Griesemer**, **Ken Thompson** và **Rob Pike** vào năm 2007. Mục đích của việc thiết kế ngôn ngữ mới bắt nguồn từ một số phản hồi về tính chất phức tạp của C++11 và nhu cầu thiết kế lại ngôn ngữ C trong môi trường network và multi-core.
4
4
5
-
Vào giữa năm 2008, hầu hết các tính năng được thiết kế trong ngôn ngữ được hoàn thành, họ bắt đầu hiện thực trình biên dịch (compiler) và bộ thực thi (runtime) với **Russ Cox** là nhà phát triển chính. Trước năm 2010, ngôn ngữ Go dần dần được hoàn thiện. Vào tháng 9 cùng năm, ngôn ngữ Go chính thức được công bố dưới dạng Open source.
5
+
Vào giữa năm 2008, hầu hết các tính năng được thiết kế trong ngôn ngữ được hoàn thành, họ bắt đầu hiện thực trình biên dịch (compiler) và Go runtime với **Russ Cox** là nhà phát triển chính. Trước năm 2010, ngôn ngữ Go dần dần được hoàn thiện. Vào tháng 9 cùng năm, ngôn ngữ Go chính thức được công bố dưới dạng Open source.
6
6
7
7
Ngôn ngữ Go thường được mô tả là "Ngôn ngữ tựa C" hoặc là "Ngôn ngữ C của thế kỉ 21". Từ nhiều khía cạnh, ngôn ngữ Go thừa hưởng những ý tưởng từ ngôn ngữ C, như là cú pháp, cấu trúc điều khiển, kiểu dữ liệu cơ bản, thủ tục gọi, trả về, con trỏ, v,v.., hoàn toàn kế thừa và phát triển ngôn ngữ C, hình bên dưới mô tả sự liên quan của ngôn ngữ Go với các ngôn ngữ khác.
8
8
@@ -33,9 +33,9 @@ Một vài những tính năng khác của ngôn ngữ Go đến từ một số
33
33
34
34
Tính chất concurrency của Go đến từ học thuyết [Commutative sequential processes (CSP)](https://www.cs.cmu.edu/~crary/819-f09/Hoare78.pdf) được công bố bởi Tony Hoare tại Bell Labs vào năm 1978. Bài báo khoa học về CSP nói rằng chương trình chỉ là một tập hợp các tiến trình được chạy song song, mà không có sự chia sẻ về trạng thái, sử dụng `channel` cho việc giao tiếp và điều khiển đồng bộ.
35
35
36
-
Học thuyết CSP của Tony Hoare chỉ là một mô hình lập trình với những khái niệm cơ bản về concurrency (tính đồng thời), nó cũng không hẳn là một ngôn ngữ lập trình. Qua việc thiết kế Go, Rob Pike đã tổng hợp nhiều thập kỉ trong việc ứng dụng học thuyết CSP trong việc xây dựng ngôn ngữ lập trình.
36
+
Học thuyết CSP của Tony Hoare chỉ là một mô hình lập trình với những khái niệm cơ bản về concurrency (tính đồng thời), nó cũng không hẳn là một ngôn ngữ lập trình. Qua việc thiết kế Go, Rob Pike đã tổng hợp nhiều thập kỷ trong việc ứng dụng học thuyết CSP trong việc xây dựng ngôn ngữ lập trình.
37
37
38
-
Ngôn ngữ [Erlang](https://en.wikipedia.org/wiki/Erlang_(programming_language)) là một hiện thực khác của học thuyết **CSP**.
38
+
Ngôn ngữ **Erlang** là một hiện thực khác của học thuyết **CSP**, bạn có thể tìm kiếm thông tin về ngôn ngữ này trên [trang chủ Erlang](https://www.erlang.org/).
39
39
40
40
Hình dưới chỉ ra lịch sử phát triển của ngôn ngữ Go qua codebase logs.
41
41
@@ -59,7 +59,7 @@ Có thể nhìn thấy từ những submission log rằng ngôn ngữ Go đượ
59
59
</div>
60
60
<br/>
61
61
62
-
Trong vòng những năm gần đây, Go là một ngôn ngữ được ưa chuộng khi viết các chương trình có kiến trúc Micro Services, vì những đặc tính nhỏ gọn, biên dịch nhanh, import thư viện từ github, cú pháp đơn giản nhưng hiện đại.
62
+
Trong vòng những năm gần đây, Go là một ngôn ngữ được ưa chuộng khi viết các chương trình Micro Services, vì những đặc tính nhỏ gọn, biên dịch nhanh, import thư viện từ github, cú pháp đơn giản nhưng hiện đại.
Copy file name to clipboardExpand all lines: ch1-basic/ch1-02-hello-revolution.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -210,7 +210,7 @@ Ngữ pháp của Alef về cơ bản giống như ngôn ngữ C. Nó có thể
210
210
211
211
## 1.2.5. Limbo - Sean Dorward, Phil Winterbottom, Rob Pike, 1995
212
212
213
-
Limbo (Hell) là ngôn ngữ lập trình để phát triển các ứng dụng phân tán chạy trên máy tính nhỏ. Nó hỗ trợ lập trình mô-đun, kiểm tra kiểu mạnh vào thời gian biên dịch và thời gian chạy, liên lạc bên trong process thông qua đường ống (pipeline), có bộ thu gom rác tự động. Có các loại dữ liệu trừu tượng đơn giản. Limbo được thiết kế để hoạt động an toàn ngay cả trên các thiết bị nhỏ mà không cần bảo vệ bộ nhớ phần cứng. Ngôn ngữ Limbo chạy chủ yếu trên hệ thống Inferno.
213
+
Limbo (Hell) là ngôn ngữ lập trình để phát triển các ứng dụng phân tán chạy trên máy tính nhỏ. Nó hỗ trợ lập trình mô-đun, kiểm tra kiểu mạnh vào thời gian biên dịch và thời gian chạy, liên lạc bên trong process thông qua channel, có bộ thu gom rác tự động. Có các loại dữ liệu trừu tượng đơn giản. Limbo được thiết kế để hoạt động an toàn ngay cả trên các thiết bị nhỏ mà không cần bảo vệ bộ nhớ phần cứng. Ngôn ngữ Limbo chạy chủ yếu trên hệ thống Inferno.
214
214
215
215
Phiên bản Limbo của chương trình "Hello World" như sau:
Copy file name to clipboardExpand all lines: ch1-basic/ch1-03-array-string-and-slice.md
+5-5Lines changed: 5 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -125,7 +125,7 @@ var decoder2 = [...]func(io.Reader) (image.Image, error){
125
125
varunknown1 [2]interface{}
126
126
varunknown2 = [...]interface{}{123, "Hello!"}
127
127
128
-
// Mảng pipe
128
+
// Mảng channel
129
129
varchanList = [2]chanint{}
130
130
```
131
131
@@ -142,16 +142,16 @@ var f = [...]int{}
142
142
143
143
Một array có chiều dài 0 thì không chiếm không gian lưu trữ.
144
144
145
-
## 1.3.2 String
145
+
## 1.3.2. String
146
146
147
147
<divalign="center">
148
-
<img src="../images/1-3-string.jpeg" width="600">
148
+
<img src="../images/ch1-string.png" width="400">
149
149
</div>
150
150
<br/>
151
151
152
152
`string` cũng là một array của các `byte` dữ liệu, nhưng khác với array những phần tử của string là [immutable](https://en.wikipedia.org/wiki/Immutable_object)
153
153
154
-
Cấu trúc `reflect.StringHeader` được định nghĩa với:
154
+
Cấu trúc [reflect.StringHeader](https://golang.org/src/reflect/value.go?s=56526:56578#L1873) được dùng để biểu diễn string :
155
155
156
156
```go
157
157
typeStringHeaderstruct {
@@ -197,7 +197,7 @@ s1 := "hello world"[:5]
197
197
s2:="hello world"[6:]
198
198
```
199
199
200
-
Tương tự như array, String cũng có một hàm build-in là `len` dùng để trả về chiều dài của string, ngoài ra bạn có thể dùng `reflect.StringHeader` để truy xuất chiều dài của string theo cách như sau
200
+
Tương tự như array, String cũng có một hàm built-in là `len` dùng để trả về chiều dài của string, ngoài ra bạn có thể dùng `reflect.StringHeader` để truy xuất chiều dài của string theo cách như sau
Copy file name to clipboardExpand all lines: ch1-basic/ch1-04-func-method-interface.md
+19-3Lines changed: 19 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -89,9 +89,9 @@ Ta thường sử dụng `defer` cho việc đóng hoặc giải phóng tài ngu
89
89
if err != nil {
90
90
panic("cannot create file")
91
91
}
92
+
93
+
// chắc chắn file sẽ được close dù hàm có bị panic hay return
92
94
defer f.Close()
93
-
// no matter what happens here file will be closed
94
-
// for sake of simplicity I skip checking close result
95
95
fmt.Fprintf(f,"hello")
96
96
}
97
97
```
@@ -135,6 +135,15 @@ Ta thường sử dụng `defer` cho việc đóng hoặc giải phóng tài ngu
135
135
136
136
### Slice trong Function
137
137
138
+
<div align="center">
139
+
<img src="../images/slice_1.png" width="300">
140
+
<br/>
141
+
<span align="center">
142
+
<i>Minh hoạ slice</i>
143
+
</span>
144
+
</div>
145
+
<br/>
146
+
138
147
Mọi thứ trong Go đều được truyền theo kiểu pass by value, slice cũng thế. Nhưng vì giá trị của slice là một *header* (chứa con trỏ tới dữ liệu array bên dưới) nên khi truyền slice vào hàm, quá trình copy sẽ bao gồm luôn địa chỉ tới array chứa dữ liệu thực sự.
139
148
140
149
Ví dụ sau cho thấy ý nghĩa của việc truyền tham số kiểu slice vào hàm thay vì array:
@@ -263,7 +272,6 @@ func main() {
263
272
Trong một số tình huống, ta quan tâm nhiều hơn đến một chuỗi thao tác ví dụ như `Read` đọc một số mảng và sau đó gọi `Close` để đóng, trong ngữ cảnh này, người dùng không quan tâm đến kiểu của đối tượng, miễn là nó có thể đáp ứng được các thao tác của `Read` và `Close`. Tuy nhiên trong các biểu thức phương thức của `ReadFile`, `CloseFile` có chỉ rõ kiểu `File` trong tham số kiểu sẽ khiến chúng không bị phụ thuộc vào đối tượng nào cụ thể. Việc này có thể khắc phục bằng cách sử dụng thuộc tính closure (closure property):
264
273
265
274
```go
266
-
267
275
func main() {
268
276
var data []byte
269
277
@@ -400,6 +408,14 @@ Duck-typing với ý tưởng đơn giản:
400
408
401
409
> If something looks like a duck, swims like a duck and quacks like a duck then it’s probably a duck.
402
410
411
+
<div align="center">
412
+
<img src="../images/duck-typing.png" width="300">
413
+
<br/>
414
+
<span align="center">
415
+
</span>
416
+
</div>
417
+
<br/>
418
+
403
419
Ví dụ có một interface con vịt, xác định khả năng `Quacks`:
Copy file name to clipboardExpand all lines: ch1-basic/ch1-05-mem.md
+17-31Lines changed: 17 additions & 31 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,13 +2,10 @@
2
2
3
3
Thời gian đầu, CPU chỉ có một lõi duy nhất, các ngôn ngữ khi đó sẽ theo mô hình lập trình tuần tự, điển hình là ngôn ngữ C. Ngày nay, với sự phát triển của công nghệ đa xử lý, để tận dụng tối đa sức mạnh của CPU, mô hình lập trình song song hay [multi-threading](https://en.wikipedia.org/wiki/Multithreading_(computer_architecture)) thường thấy trên các ngôn ngữ lập trình ra đời. Ngôn ngữ Go cũng phát triển mô hình lập trình song song rất hiệu quả với khái niệm Goroutines.
4
4
5
-
<divalign="center"width="600">
6
-
<imgsrc="../images/concurency.jpg">
7
-
<br/>
8
-
<spanalign="center"><i>Quá trình khởi tạo package</i></span>
@@ -17,15 +14,19 @@ Goroutines là một đơn vị concurrency của ngôn ngữ Go. Việc khởi
17
14
Đầu tiên, system thread sẽ có một kích thước vùng nhớ stack cố định (thông thường vào khoảng 2MB). Vùng nhớ stack chủ yếu được dùng để lưu trữ những tham số, biến cục bộ và địa chỉ trả về khi chúng ta gọi hàm.
18
15
19
16
Kích thước cố định của stack sẽ dẫn đến hai vấn đề:
20
-
* Lãng phí vùng nhớ đối với chương trình đơn giản
21
-
* StackOverflow với những chương trình gọi hàm phức tạp.
17
+
* Stack overflow với những chương trình gọi hàm đệ quy sâu.
18
+
* Lãng phí vùng nhớ đối với chương trình đơn giản.
19
+
22
20
23
21
Giải pháp cho vấn đề này chính là cấp phát linh hoạt vùng nhớ stack:
24
22
* Một Goroutines sẽ được bắt đầu bằng một vùng nhớ nhỏ (khoảng 2KB hoặc 4KB).
25
23
* Khi gọi đệ quy sâu (không gian stack hiện tại là không đủ) Goroutines sẽ tự động tăng không gian stack (kích thước tối đa của stack có thể được đạt tới 1GB)
26
24
* Bởi vì chi phí của việc khởi tạo là nhỏ, chúng ta có thể dễ dàng giải phóng hàng ngàn goroutines.
27
25
28
-
Bộ thực thi (runtime) Go có riêng cơ chế định thời cho Goroutines, nó dùng một số kỹ thuật để ghép M Goroutines trên N thread của hệ thống. Cơ chế định thời Goroutines tương tự với cơ chế định thời của `kernel` nhưng chỉ ở mức chương trình. Biến `runtime.GOMAXPROCS` quy định số lượng system thread hiện thời chạy trên các Goroutines.
26
+
Go runtime có riêng cơ chế định thời cho Goroutines, nó dùng một số kỹ thuật để ghép M Goroutines trên N thread của hệ thống. Cơ chế định thời Goroutines tương tự với cơ chế định thời của `kernel` nhưng chỉ ở mức chương trình. Biến `runtime.GOMAXPROCS` quy định số lượng system thread hiện thời chạy trên các Goroutines.
* Package `sync/atomic` sẽ hỗ trợ những tác vụ atomic cho những kiểu cơ bản.
199
-
* Cho việc đọc và ghi một đối tượng phức tạp, `atomic.Value` sẽ hỗ trợ hai hàm `Load` và `Store` để load và save dữ liệu, trả về giá trị và tham số là `interface{}` nó có thể được sử dụng trong một vài kiểu đặc biệt.
199
+
Package `sync/atomic` sẽ hỗ trợ những tác vụ atomic cho những kiểu cơ bản.
200
+
201
+
Cho việc đọc và ghi một đối tượng phức tạp, `atomic.Value` sẽ hỗ trợ hai hàm `Load` và `Store` để load và save dữ liệu, trả về giá trị và tham số là `interface{}` nó có thể được sử dụng trong một vài kiểu đặc biệt.
* Việc khởi tạo và thực thi chương trình Go luôn luôn bắt đầu bằng hàm `main.main`.
260
-
* Tuy nhiên nếu package `main` import các package khác vào, chúng sẽ được import theo thứ tự string của tên file và tên thư mục.
261
-
* Nếu một package được import nhiều lần, thì những lần import sau được bỏ qua.
262
-
* Nếu các package lại import các package khác nữa, chúng sẽ import vào khởi tạo các biến theo chiều sâu như hình bên dưới:
263
-
264
-
<divalign="center"width="600">
265
-
<imgsrc="../images/ch1-12-init.ditaa.png">
266
-
<br/>
267
-
<spanalign="center"><i>Quá trình khởi tạo package</i></span>
268
-
</div>
269
-
<br/>
270
-
271
-
* Nếu hàm `init` giải phóng một Goroutine mới với từ khóa `go`, thì Goroutine và `main.main` sẽ được thực thi một cách tuần tự. Bởi vì tất cả hàm `init` và hàm `main` sẽ được hoàn thành trong cùng một thread, nó cũng sẽ thoả mãn thứ tự về mô hình nhất quán.
272
-
273
-
## 1.5.5 Khởi tạo một Goroutine
259
+
## 1.5.4. Khởi tạo một Goroutine
274
260
275
261
Mệnh đề đứng sau từ khóa `go` sẽ tạo ra một Goroutine mới, ví dụ :
276
262
@@ -289,9 +275,9 @@ func hello() {
289
275
}
290
276
```
291
277
292
-
## 1.5.6 Giao tiếp thông qua kênh Channel
278
+
## 1.5.5. Giao tiếp thông qua kênh Channel
293
279
294
-
*Tác vụ gửi trên một unbufferred Channel luôn luôn xảy ra trước tác vụ nhận, dùng tính chất này cho việc đồng bộ giữa các goroutines.
280
+
Tác vụ gửi trên một unbufferred Channel luôn luôn xảy ra trước tác vụ nhận, dùng tính chất này cho việc đồng bộ giữa các goroutines.
295
281
296
282
```go
297
283
// dùng channel done để đồng bộ thứ tự thực thi
@@ -341,7 +327,7 @@ func main() {
341
327
342
328
Dòng `select{}` cuối cùng là một mệnh đề lựa chọn một empty channel sẽ làm cho main thread bị block, ngăn chặn chương trình kết thúc sớm. Tương tự `for{}` và `<- make(chan int)` nhiều hàm khác sẽ đạt được kết quả tương tự.
343
329
344
-
## 1.5.7 Tác vụ đồng bộ không tin cậy
330
+
## 1.5.6. Tác vụ đồng bộ không tin cậy
345
331
346
332
Như chúng ta phân tích trước, đoạn code sau sẽ không đảm bảo thứ tự in ra kết quả bình thường. Việc chạy thực sự bên dưới sẽ có một xác suất lớn kết quả sẽ không bình thường.
0 commit comments