12/08/2018, 16:40

Go part 2

Tất cả các chương trình của Go đều được tổ chức các files lại với nhau thành một nhóm được gọi là packages, do đó code có thể được tái sử dụng, được include vào trong project khác Ví dụ về package http trong thư viện của Go net/http/ cgi/ cookiejar/ testdata/ fcgi/ ...

Tất cả các chương trình của Go đều được tổ chức các files lại với nhau thành một nhóm được gọi là packages, do đó code có thể được tái sử dụng, được include vào trong project khác Ví dụ về package http trong thư viện của Go

net/http/
    cgi/
    cookiejar/
        testdata/
    fcgi/
    httptest/
    httputil/
    pprof/
    testdata/

Main packages

Main packages có ý nghĩa đặc biệt trong Go, Tất cả các chương trình bạn xây dựng trong Go đều phải có package main này. Khi trình biên dịch thấy main package này, thì nó cũng đồng thời phải tìm ra một phương thức main() , nếu phương thức này không được tìm thấy thì binary executable sẽ không được tạo ra, Phương thức main() này là điểm bắt đầu của chương trình và nếu không có nó thì chương trình sẽ không có điểm chạy đầu hay nói cách khác là nó không biết chạy bắt đầu từ đâu.

import

Câu lệnh import này nói cho trình biên dịch biết nơi nào trên cần tìm package muốn import. Khi bạn sử dụng từ khoá import tức là bạn đã nói cho trình biên dịch biết bạn muốn tham chiếu code nằm trong package nếu bạn cần phải import nhiều package thì có thể sử dụng import kiểu block

import (
    "fmt"
    "strings"
)

Những packages này được tìm thấy trên ổ đĩa, dựa vào đường dẫn tương đối tới thực mục được tham chiếu bởi Go environment. Những package ở trong standard lib được đặt ở nơi mà Go đã cài đặt trên máy.

giả sử Go được cài đặt ở /usr/local/go và GOPATH được set /home/project:/home/mybraries thì trình biên dịch sẽ tìm gói net/http theo thứ tự sau:

/usr/local/go/src/pkg/net/http
/home/myproject/src/net/http
/home/mylibraries/src/net/http

Nếu theo thứ tự trên mà trình biên dịch không tìm ra thì sẽ thông báo lỗi.

ngoài ra bạn cũng có thể imort một package từ trên internet (remote import)

import "github.com/account_name/package"

Khi import một path có chứa url, Go tooling sẽ fetch package từ DVCS(distributed version control systems ) và đưa code đó vào GOPATH bằng câu lệnh go get, go get sẽ lấy bất cứ một url hoặc có thể được dùng để load các gói dependence.

Bạn cũng có thể đặt tên cho các gói được import ví dụ

 package main

 import (
     "fmt"
     myfmt "mylib/fmt"
 )

 func main() {
     fmt.Println("Standard Library")
     myfmt.Println("mylib/fmt")
 }

Trình biên dịch của Go sẽ build fail và trả về error nếu bạn import package mà bạn ko dùng đến nó.

init

Mỗi package có thể có nhiều các init function được gọi tại thời điểm bắt đầu thực thi, tất cả các init function này sẽ được trình biên dịch lên schedule để chạy init function thích hợp cho việc setup package khởi tạo các biến hay thực thi một số tác vụ nào đó trước khi chạy vào phần chính của chương trình.

 package postgres
 import (
     "database/sql"
 )
 func init() {
     sql.Register("postgres", new(PostgresDriver))
 }

bạn có thể gõ go trên terminal để xem list tool của go Build go file bằng câu lệnh

go build hello.go

Sẽ sinh ra một file build tên hello Để clean file này đi dùng lệnh

go clean go clean hello.go

Để thực thi một chương trình bạn có thể run file đã build hoặc run trực tiếp bằng câu lệnh sau

go run hello.go

go run sẽ thực thi cả 2 việc build và thực thi chương trình sau khi đã build.

go vet

Câu lệnh này được dùng để check các lỗi thông thường như, nó cũng giống như câu lệnh ruby -c filename.rb trong ruby

  • Sai parameter
  • Tên của method không đúng quy tắc
  • Các tags không đúng struct giả sử tôi sẽ xóa chữ p ở package đi và run code
go vet hello.go

kết quả là

can't load package: package main: 
test.go:1:1: expected 'package', found 'IDENT' ackage

go format

go format là một chức năng khá hay được nhiều người sử dụng cho việc format code như space, indent làm cho code của bạn dễ nhìn hơn ...

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

gải sử hàm main tôi để code trên dấu ngoặc xoắn sau khi sử dụng lệnh

gofmt -w hello.go

code trong file hello.go sẽ được format gọn gàng dễ đọc lại như sau

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

Array trong Go là kiểu dữ liệu fixed-length, nó chứa các element của cùng một kiểu dữ liệu liên tiếp nhau, kiểu dữ liệu có thể là kiểu nguyên thuỷ buil-in như integer, string hay struct. Các thành phần trong mảng kết nối với nhau thành một chuỗi liên tiếp và các element này phải cùng một kiểu dữ liệu và ta có thể access vào mảng thông qua vị trí của index.

Khai báo một mảng kiểu integer

var array [5]int

Mỗi một khi được khai báo thì cả về kiểu dữ liệu và độ dài của mảng sẽ không thể được thay đổi nữa. Nếu muốn có nhiều element hơn nữa thì bạn phải tạo thêm một mảng mới và copy value của nó sang. Khi một mảng được khởi tạo thì giá trị mặc định của nó sẽ là 0. Bạn có thể thấy nó khác với ruby, đối với ruby thì khi khai báo ta không cần khai báo kiểu và độ dài mảng. Thêm nữa là kiểu dữ liệu của các phần tử mảng không cần phải giống nhau.

Thao tác với mảng

Đối với mảng trong Go thì nó rất nhanh và hiệu quả bởi bộ nhớ của nó được bố trí một cách có trình tự, rất hiệu quả trong việc access vào một element cụ thể (dự là nhanh hơn ruby :v) Để truy cập vào một element ta sử dụng toán tử []

array := [5]int{1,2,3,4,5}
array[2] # 3

Bạn có thể khai báo một mảng kiểu con trỏ (pointer)

array := [5]*int{0: new(int), 1: new(int)}
#gán giá trị cho mảng 
*array[0] = 10
*array[1] = 20

và mảng sau khi được gán sẽ như sau:

Một mảng có thể gán bằng các mảng khác có cùng kiểu dữ liệu

var arr := [5]string
var arr2:= [5]string{0: “Red”, 1: “Blue”, “Green”, “Yellow”, “Pink”}
arr = arr2 # copy arr2 sang arr

Chú ý là chỉ khi 2 mảng được khai báo cùng kiểu cùng độ dài mới được gán cho nhau nếu không sẽ có lỗi sinh ra trong quá trình biên dịch

Gán một mảng pointer sang mảng pointer khác

var array1 [3]string
var array2 := [3]*string{new(string), new(string), new(string)}
*array[0]= ”Red”
*array[1]= ”Blue”
*array[2]= “Green”

# gán mảng pointer
array1 = array2

Như trên ta có 2 mảng pointer cùng trỏ tới cùng một string ở mỗi element. Điều đó có nghĩa là bạn chỉ copy giá trị con trỏ chứ không copy giá trị mà con trỏ trỏ tới.

Mảng đa chiều

Bạn có thể sử dụng mảng 2 chiều cho mục đích khác nhau như quan hệ cha con … Khai báo mảng 2 chiều:

var array [4][2]int
array := [4][2]int{{10, 11}, {20, 21}, {30, 31}, {40, 41}}
array := [4][2]int{1: {20, 21}, 3: {40, 41}}
array := [4][2]int{1: {0: 20}, 3: {1: 41}}

Tham khảo

Go in action https://livebook.manning.com/#!/book/go-in-action/chapter-1/

0