Thứ Tư, 22 tháng 4, 2020

[Golang] Map


I. Khái niệm về Map


Map là một built-in Type trong golang. Map associate một value tới một key. Value có thể được retrieved bằng cách sử dụng key tương ứng.

II. How to create a Map


Map có thể được tạo bằng 2 cách:

1. Tạo Map với make function


Syntax

map := make(map[key-type]value-type)

Ví dụ:

personSalary := make(map[string]int)

với cú pháp trên, ta vừa tạo một map personSalary với key là string và value dạng int

Zero value của Map là nil. Nếu chúng ta add một item vào một nil map, sẽ gây panic. Vì vậy, ta phải khởi tạo initialized map  với make trước khi sử dụng.

2. Short hand declaration



Ta có thể tạo một map bằng cách gọi trực tiếp
map := map[string]int{ "key": 1 }

III. Adding items vaò map


Có thể add items vào map dựa vào cấu trúc sau:

map[key] = value

Ví dụ:
package main

import (  
    "fmt"
)

func main() {  
    personSalary := make(map[string]int)
    personSalary[" person1"] = 12000
    personSalary["person2"] = 15000    personSalary["person3"] = 9000    fmt.Println("personSalary map contents:", personSalary)
}st

Run chương trình trên, output sẽ như sau:

personSalary map contents: map[person1:12000 person2:15000 person3:9000]

Những type nào có thể sử dụng làm key của một map?


Tất cả những comparable type như: bolean, integer, float, string, comflex ... đều có thể sử dụng làm key của một map.

Key của một map là không thể trùng nhau.

IV. Accessing items của map


Value của map được retrieved using key tương ứng

value := map[key] 

Chuyện gì sẽ xảy nếu một key được retrieved không tồn tại?


Khi đó, value được trả về sẽ là zero value của key đó. Ví dụ "" với key là string, 0 với key là int ...


package main

import (  
    "fmt"
)

func main() {  
    personSalary := map[string]int{
        "person1": 12000,
        "person2": 15000,    }
    personSalary["person3"] = 9000    employee := "person1"    fmt.Println("Salary of", employee, "is", personSalary[employee])
    fmt.Println("Salary of person4 is", personSalary["person4"])}

khi đó, output sẽ trả về:

Salary of person1 is 15000  
Salary of person4 is 0 

Làm thế nào chúng ta biết được một key có nằm trong map đó hay không?


Check với syntax sau:


value, ok := map[key]  

  • Nếu key nằm trong map, ok sẽ trả về true
  • Nêú key không nằm trong map, ok sẽ trả về false


Để iterate all items in map, sử dụng range form của for loop 

package main

import (  
    "fmt"
)

func main() {  
    personSalary := map[string]int{
        "person1": 12000,        "person2": 15000,    }
    personSalary["person3"] = 9000    fmt.Println("All items of a map")
    for key, value := range personSalary {
        fmt.Printf("personSalary[%s] = %d\n", key, value)
    }

}

Output của chương trình trên:
All items of a map  
personSalary[person1] = 9000  
personSalary[person2] = 12000  
personSalary[person3] = 15000  

V. Deleting Item trong một map


Sử dụng delete func với syntax sau:
delete(map, key) 

VI. Length của một map



length của map có thể được xác đinh bởi len() func

len(map) 


VII. Map là một reference Type


Giống như slice, Map là một reference type. Nghĩa là, khi map được assign tới một value, cả hai đối tượng sẽ được point tới cùng một internal data structure. Vì vậy, khi ta thay đổi biến hoặc map, đối tượng còn lại sẽ thay đổi theo

package main

import (  
    "fmt"
)

func main() {  
    personSalary := map[string]int{
        "person1": 12000,
        "person2": 15000,    }
    personSalary["person3"] = 9000    fmt.Println("Original person salary", personSalary)
    newPersonSalary := personSalary
    newPersonSalary["person3"] = 18000    fmt.Println("Person salary changed", personSalary)

}

Trong chương trình trên, personSalary sẽ được assign tới newPersonSalary. vì vậy, khi ta thay đổi newPersonSalary, personSalary cũng sẽ thay đổi theo.

Output của chương trình sẽ là:
Original person salary map[person1:12000 person2:15000 person3:9000]  
Person salary changed map[person1:12000 person2:15000 person3:18000]

VIII. Làm thế nào để compare hai map với nhau?


Hai map không thể compare sử dụng dấu ==.  == chỉ được sử dụng để check khi map là nil.
Để check hai map bằng nhau, chúng ta chỉ có thể check lần lượt từng phần tử trong mỗi map là bằng nhau, one by one



Thứ Hai, 20 tháng 4, 2020

[Golang] Variadic Functions


Khái niệm về Variadic Function

Một function thường nhận một số lượng fixed arguments. Một Variadic Function là một function nhận một số lượng arguments có thể thay đổi được (a variable number of arguments). Nếu parameter cuối cùng được bắt đầu với dấu ellipsis ..., thì function có thể nhận bất kì argument nào cho parameter đó.

Chú ý rằng, chỉ có parameter cuối cùng có thể variadic.

Syntax của một variadic function:



func hello(a int, b ...int) {
}


ở trên, hello là một Variadic Function. Parameter b là một variadic parameter được prefixed bằng dấu ellipsis ... . b có thể nhận bất cứ arguments nào được truyền vào.

Ta có thể gọi func hello với số lượng argument thay đổi:
hello(1)
hello(1,2)
hello(1, 2 , 4, 5, 6 )


Trong line 1, chúng ta pass b với một zero argument. ok, it's still work fine :)
Trong line 2, chúng ta pass b với một argument 2.
Trong line 3, chúng ta pass b với 4 argument: 2, 4, 5, 6

[Design Pattern] [Golang] Phân chia tỉ lệ phần trăm request cho các action khác nhau

Bài toán đặt ra


Khi bạn có một service cần xử lý request và bạn có 2 cách A và B để thực hiện luồng handle request đó. Bạn cần phân chia 40 % request sẽ được xử lý theo các A và 60 % request sẽ được xử lý theo cách B. Khi đó, service được thiết kế như thế nào?

Solution


Solution 1


Golang cung cấp hàm random và xử lý bài toán trên như sau:
1. Dùng hàm random, generate một số x random với nằm trong khoảng [0,100)
2. Nêú x < 40, request handle theo hướng A
3. Nếu x > 40, request handle theo hướng B

simple code:

package main
import (
   "fmt"  
   "math/rand")

func main() {
   max := 100   
   count1 := 0   
   count2 := 0   
   for i := 0; i < 1000; i ++ {
      x := rand.Intn(max)
      fmt.Println(x)
      if x < 40 {
         count1 +=1      } else {
         count2 += 1      }
   }
   fmt.Println(count1, count2)
}

Đã test thực tế, tỉ lệ % khá chính xác.

Thứ Bảy, 11 tháng 4, 2020

[Golang] Array and Slice


Array

An Array là một numbered sequence of elements (chuỗi của các phần tử được đánh số) có cùng single types với một fixed length - length của một array là không thể change được.

Ví dụ về một array:

var x [5] int

  • Khai báo một array x chứa các elements có type là int
  • Array x có độ dài là 5
  • Khi khở tạo, tất cả các phần tử sẽ có giá trị là 0. x sẽ có giá trị như sau: [0 0 0 0 0]


Ta có thể add giá trị cho phần tử thứ 5 như sai:
x[4] = 100
Trong đó, 4 là index của phần tử thứ 5 trong array. Chú ý rằng, similar to các ngôn ngữ khác:

  • index luôn được bắt đầu bằng 0
  • index kết thúc bằng -1


Ta cũng có thể khởi tạo array như sau, short hand declaration:


x := [5]int64{1,2,3,4,5}

Chúng ta cũng có thể bỏ qua length của array khi sử dụng short hand declaration sử dụng ... :

x := [...]int{1,2,3} 

Khi đó, compiler  sẽ tự define leng của array là 3.

Slice


Slice là một segment (một đoạn) của một array. Tương tự như array, Slice chỉ hold các phần tử có củng type, indexible  và có một length. Tuy nhiên, length của một slice có thể thay đổi được.

Khi tạo một slice, chúng ta có thể "bỏ trống" capacity :

x:= []int{1,2,3}

Chúng ta cũng có thể tạo ra một Slice sử dụng Make:

x := make([]int, 5, 10)

Hàm make return một slice được associated (tham chiếu) đến một underlying array có:
  • length = 5
  • capacity = 10

khi sử dụng make, chúng ta cũng có thể bỏ qua length và capacity của slice
x := make([]int)
Note: Khi sử dụng make, sẽ return lại một initialed value T, chứ không return *T do array (giống với map, channel) là những type cần phải khởi taọ trước rồi mới sử dụng được.

Slice Functions

1. Append

Tạo một slice mới từ slice ban đầu và append các phần tử mới vào cuối:
x := []int{1,2,3}         // x: [1,2,3]
y := append(x, 4)       // y: [1,2,3,4]

2. Copy

        x := []int{1,2,3}         // x: [1,2,3]
        y := make([]int, 2)
       copy(y, x)
     
Sau khi chạy chương trình trên:


  • Slice x: [1,2,3]
  • Slice y: [1,2]


Do length của y là 2 nên nó chỉ copy được 2 giá trị đầu trong slice x, còn giá trị thứ 3 không đuọc copy vì y không còn chỗ chứa


Kết luận:

Array và Slice:

Giống nhau:
  • Cùng là numbered sequence of elements có cùng type

Khác nhau:

  • Length của Array là cố định, không đổi được. Length của slice thay đổi được