thảo luận Tất tần tật về Go (Golang)

https://www.techempower.com/benchmarks/#section=data-r18&hw=ph&test=db&l=zcasqn-f

Đẹp nhưng speed khá 1 ty chứ python ruby vốn dĩ chậm rồi.

Thằng Nim eco hẻo quá.

Nói chung vẫn thua go :doubt:
speed của crystal hay nim ăn đứt go, vì chúng nó backend là LLVM/GCC (nim thì transpile sang c, lúc đó thì dùng clang hay gcc để compile đều được, crystal thì transpile sang llvm opcode), go thì được cái compile nhanh, chứ optimization thì kém hơn (không gõ dùng gcc-go hay go-llvm các kiểu thì có khá hơn không).

cơ mà nim no hope vãi, tôi để ý thằng này từ hồi nó còn tên là nimrod, phải nói là mỗi lần nó ra release mới là một lần giảm hứng thú, core dev toàn quan tâm vấn đề đâu đâu, nhét một đống feature vào mà không suy nghĩ kỹ, implementation cũng half baked, stdlib thì vẫn sơ sài, document thì gần như không có.

crystal thì đầu năm có tí phát triển mà sau đợt covid này lại dẹo rồi, thôi lại đợi năm sau :LOL:
 
speed của crystal hay nim ăn đứt go, vì chúng nó backend là LLVM/GCC (nim thì transpile sang c, lúc đó thì dùng clang hay gcc để compile đều được, crystal thì transpile sang llvm opcode), go thì được cái compile nhanh, chứ optimization thì kém hơn (không gõ dùng gcc-go hay go-llvm các kiểu thì có khá hơn không).

cơ mà nim no hope vãi, tôi để ý thằng này từ hồi nó còn tên là nimrod, phải nói là mỗi lần nó ra release mới là một lần giảm hứng thú, core dev toàn quan tâm vấn đề đâu đâu, nhét một đống feature vào mà không suy nghĩ kỹ, implementation cũng half baked, stdlib thì vẫn sơ sài, document thì gần như không có.

crystal thì đầu năm có tí phát triển mà sau đợt covid này lại dẹo rồi, thôi lại đợi năm sau :LOL:

Làm web thì kiếm kết quả bench web thôi, chứ nhanh mà bench real web use case chậm thì cũng vậy :sneaky:
 
Thì tôi post link rồi đó
ạch, tự :beat_brick:
cơ mà ấn tượng của tôi là nim/crystal ăn đứt go về performance trong vài bài test của vài individual.
ví dụ: https://github.com/kostya/benchmarks

techempower thì lâu rồi cũng không vào cho nên không để ý lắm :">

p/s: đệt hôm nay xem lại thì thấy golang performance lên nhanh vãi vkl, đúng là mấy cái này đíu check thường xuyên sẽ thành lạc hậu :"> ngày trước tôi toàn thấy golang toàn chậm x2 x3 so với nim/crystal, giờ thì đã xêm xêm, kinh vl.
 
Last edited:
ạch, tự :beat_brick:
cơ mà ấn tượng của tôi là nim/crystal ăn đứt go về performance trong vài bài test của vài individual.
Go nó ngôn ngữ không quá xấu, simple enough, speed tạm tạm cũng hơn khối ông Node, Ruby, Python, PHP nên giờ đc adopt kha khá chứ chửi nó thì cũng chịu thôi, ko có ngôn ngữ nào vừa long lập trình viên. :confident:

Mấy ngôn ngữ lập trình mới mới giờ hy vọng phải có cty lơn chống lưng, mới có đội dev optimize ngày đêm đc =((
 
Go nó ngôn ngữ không quá xấu, simple enough, speed tạm tạm cũng hơn khối ông Node, Ruby, Python, PHP nên giờ đc adopt kha khá chứ chửi nó thì cũng chịu thôi, ko có ngôn ngữ nào vừa long lập trình viên. :confident:

Mấy ngôn ngữ lập trình mới mới giờ hy vọng phải có cty lơn chống lưng, mới có đội dev optimize ngày đêm đc =((
thằng nodejs mới tởm lợm, tuy là dynamic language mà performance tương đương với mấy thằng compiled.
cơ mà tôi dùng quen ruby/elixir có stdlib tử tế rồi quay lại mấy thằng nodejs hay golang thấy bất tiện vãi, riêng mấy cái basic function để manipulate array/hashmap đã không bằng.

mà nói cái này lại nhớ thằng swift, mọi thứ đều ngon cơ mà cái stdlib như đấm vào mặt, ví dụ tôi hay evaluate language bằng mấy cái tính năng cơ bản như read file by lines các kiểu, thì trong crystal tôi chỉ cần `File.read_lines(file_path)` là được, swift thì
Code:
if let path = Bundle.main.path(forResource: "TextFile", ofType: "txt") {
    do {
        let data = try String(contentsOfFile: path, encoding: .utf8)
        let myStrings = data.components(separatedBy: .newlines)
        TextView.text = myStrings.joined(separator: ", ")
    } catch {
        print(error)
    }
}
à mà cái này là 3.0 còn đỡ, swift 2.0 mới là cái tôi chửi:
Code:
    do {
        if let path = NSBundle.mainBundle().pathForResource("TextFile", ofType: "txt"){
            let data = try String(contentsOfFile:path, encoding: NSUTF8StringEncoding)

            let myStrings = data.componentsSeparatedByCharactersInSet(NSCharacterSet.newlineCharacterSet())
            print(myStrings)
        }
    } catch let err as NSError {
        //do sth with Error
        print(err)
    }
tuy rằng có IDE nó đỡ, cơ mà nhìn mấy cái function name hay constant đều mất mẹ cảm tình :censored:

anh go cũng chả khá hơn
Code:
package main

import (
    "bufio"
    "fmt"
    "log"
    "os"
)

func main() {
    file, err := os.Open("/path/to/file.txt")
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()

    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }

    if err := scanner.Err(); err != nil {
        log.Fatal(err)
    }
}
(mấy cái này copy từ SO)
nhìn đã mất cảm tình :censored:
 
thằng nodejs mới tởm lợm, tuy là dynamic language mà performance tương đương với mấy thằng compiled.
cơ mà tôi dùng quen ruby/elixir có stdlib tử tế rồi quay lại mấy thằng nodejs hay golang thấy bất tiện vãi, riêng mấy cái basic function để manipulate array/hashmap đã không bằng.

mà nói cái này lại nhớ thằng swift, mọi thứ đều ngon cơ mà cái stdlib như đấm vào mặt, ví dụ tôi hay evaluate language bằng mấy cái tính năng cơ bản như read file by lines các kiểu, thì trong crystal tôi chỉ cần `File.read_lines(file_path)` là được, swift thì
Code:
if let path = Bundle.main.path(forResource: "TextFile", ofType: "txt") {
    do {
        let data = try String(contentsOfFile: path, encoding: .utf8)
        let myStrings = data.components(separatedBy: .newlines)
        TextView.text = myStrings.joined(separator: ", ")
    } catch {
        print(error)
    }
}
à mà cái này là 3.0 còn đỡ, swift 2.0 mới là cái tôi chửi:
Code:
    do {
        if let path = NSBundle.mainBundle().pathForResource("TextFile", ofType: "txt"){
            let data = try String(contentsOfFile:path, encoding: NSUTF8StringEncoding)

            let myStrings = data.componentsSeparatedByCharactersInSet(NSCharacterSet.newlineCharacterSet())
            print(myStrings)
        }
    } catch let err as NSError {
        //do sth with Error
        print(err)
    }
tuy rằng có IDE nó đỡ, cơ mà nhìn mấy cái function name hay constant đều mất mẹ cảm tình :censored:

anh go cũng chả khá hơn
Code:
package main

import (
    "bufio"
    "fmt"
    "log"
    "os"
)

func main() {
    file, err := os.Open("/path/to/file.txt")
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()

    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }

    if err := scanner.Err(); err != nil {
        log.Fatal(err)
    }
}
(mấy cái này copy từ SO)
nhìn đã mất cảm tình :censored:
ờ, em cứ thích if, else rõ ràng như hồi nhỏ đi học. Nhiều ông viết if rồi check null mà cứ hỏi hỏi(??) đọc code dịch mệt vcl :ops:
 
thằng nodejs mới tởm lợm, tuy là dynamic language mà performance tương đương với mấy thằng compiled.
cơ mà tôi dùng quen ruby/elixir có stdlib tử tế rồi quay lại mấy thằng nodejs hay golang thấy bất tiện vãi, riêng mấy cái basic function để manipulate array/hashmap đã không bằng.

mà nói cái này lại nhớ thằng swift, mọi thứ đều ngon cơ mà cái stdlib như đấm vào mặt, ví dụ tôi hay evaluate language bằng mấy cái tính năng cơ bản như read file by lines các kiểu, thì trong crystal tôi chỉ cần `File.read_lines(file_path)` là được, swift thì
Code:
if let path = Bundle.main.path(forResource: "TextFile", ofType: "txt") {
    do {
        let data = try String(contentsOfFile: path, encoding: .utf8)
        let myStrings = data.components(separatedBy: .newlines)
        TextView.text = myStrings.joined(separator: ", ")
    } catch {
        print(error)
    }
}
à mà cái này là 3.0 còn đỡ, swift 2.0 mới là cái tôi chửi:
Code:
    do {
        if let path = NSBundle.mainBundle().pathForResource("TextFile", ofType: "txt"){
            let data = try String(contentsOfFile:path, encoding: NSUTF8StringEncoding)

            let myStrings = data.componentsSeparatedByCharactersInSet(NSCharacterSet.newlineCharacterSet())
            print(myStrings)
        }
    } catch let err as NSError {
        //do sth with Error
        print(err)
    }
tuy rằng có IDE nó đỡ, cơ mà nhìn mấy cái function name hay constant đều mất mẹ cảm tình :censored:

anh go cũng chả khá hơn
Code:
package main

import (
    "bufio"
    "fmt"
    "log"
    "os"
)

func main() {
    file, err := os.Open("/path/to/file.txt")
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()

    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }

    if err := scanner.Err(); err != nil {
        log.Fatal(err)
    }
}
(mấy cái này copy từ SO)
nhìn đã mất cảm tình :censored:

Go với rust nó ko có try catch force dev handle error có tâm hơn. Nói chung tôi code 1 thời gian lai thấy hay hơn try catch (này cảm nhận cá nhân thôi)
 
Go với rust nó ko có try catch force dev handle error có tâm hơn. Nói chung tôi code 1 thời gian lai thấy hay hơn try catch (này cảm nhận cá nhân thôi)

Từ tư bản chủ nghĩa Error Code tiến lên xã hội chủ nghĩa Exception Try-Catch-Finally, thế rồi lại quay về ngày xưa à? :amazed:
 
Từ tư bản chủ nghĩa Error Code tiến lên xã hội chủ nghĩa Exception Try-Catch-Finally, thế rồi lại quay về ngày xưa à? :amazed:
mình viết lib toàn quăng error code để check chứ ghét kiểu quăng exception rồi catch lại lắm
 
mình viết lib toàn quăng error code để check chứ ghét kiểu quăng exception rồi catch lại lắm

Viết lib thì low-level rồi nên ném error-code để caller handle cũng dễ hiểu. Chứ ở high-level, code toàn modeling domain mà caller cứ phải handle tầng tầng lớp lớp error-code từ callee thì đúng thảm họa :beat_brick:

Nguyên tắc của tôi rất đơn giản.
1. Cái gì low-level, gần với infrastructure layer thì error-code hay exception cũng dc, tùy nhóm phát triển muốn thống nhất với nhau ntn.
2. Ở high-level, nhất là với mấy domain model phức tạp thì quất hết exception cho khỏe. Vừa đỡ rối flow, vừa thể hiện dc hết ngữ nghĩa của domain.
 
Từ tư bản chủ nghĩa Error Code tiến lên xã hội chủ nghĩa Exception Try-Catch-Finally, thế rồi lại quay về ngày xưa à? :amazed:
Vấn đề là dev dùng throw error vô tôị vạ (tôi cung từng lạm dụng cái chuyện này)

Bên Go nó handle này nhìn hơi rối tý thôi. chứ áp dụng early return pattern thì thấy bt.

Với lại phải đọc code mới biết nó có throw error hay ko. Chư bt ko có document hay đoc src có biết nó throw erro khi nao.
Viết code mà quên try catch lát hồi error văng ra ko trace log này no cũng éo biết error từ function nào.

Đưong nhiên go cũng có cái throw error mạnh tới nỗi sập server đó là panic.

nhưng thương chỉ panic khi nào error nghiêm trọng như app start éo kết nối đc database thì run làm gì nữa.


Code:
func (r *SQLRunner) BeginTx(ctx context.Context, options interface{}) (context.Context, error) {

    var SQLTxOptions *sql.TxOptions = nil

    if opts, ok := options.(*sql.TxOptions); ok {
        SQLTxOptions = opts
    }

    tx, err := r.db.BeginTx(ctx, SQLTxOptions)

    if err != nil {
        return nil, err
    }

    c := context.WithValue(ctx, r.contextKeyTx, tx)

    return c, nil
}

Cứ chỗ nào err != nil thì return error ngay. Nhiều người viết 1 đống logic trong cái khúc err != nil thì chả rối.
 
Last edited:
Từ tư bản chủ nghĩa Error Code tiến lên xã hội chủ nghĩa Exception Try-Catch-Finally, thế rồi lại quay về ngày xưa à? :amazed:

Cái exception vậy chứ tốn cost nhiều hơn error code nhiều lắm.
Go muốn optimize tốc độ ko thua quá nhiều so với C/C++ nên mình thấy đó cũng là 1 phương án hay.
 
Vấn đề là dev dùng throw error vô tôị vạ (tôi cung từng lạm dụng cái chuyện này)

Bên Go nó handle này nhìn hơi rối tý thôi. chứ áp dụng early return pattern thì thấy bt.

Với lại phải đọc code mới biết nó có throw error hay ko. Chư bt ko có document hay đoc src có biết nó throw erro khi nao.
Viết code mà quên try catch lát hồi error văng ra ko trace log này no cũng éo biết error từ function nào.

Đưong nhiên go cũng có cái throw error mạnh tới nỗi sập server đó là panic.

nhưng thương chỉ panic khi nào error nghiêm trọng như app start éo kết nối đc database thì run làm gì nữa.


Code:
func (r *SQLRunner) BeginTx(ctx context.Context, options interface{}) (context.Context, error) {

    var SQLTxOptions *sql.TxOptions = nil

    if opts, ok := options.(*sql.TxOptions); ok {
        SQLTxOptions = opts
    }

    tx, err := r.db.BeginTx(ctx, SQLTxOptions)

    if err != nil {
        return nil, err
    }

    c := context.WithValue(ctx, r.contextKeyTx, tx)

    return c, nil
}

Cứ chỗ nào err != nil thì return error ngay. Nhiều người viết 1 đống logic trong cái khúc err != nil thì chả rối.
Minh ko dùng go ,tính thử . và theo vi dụ trên thì ko lẽ mỗi lần call một func hay method nao đó thì ta phải check nil hả bác

Python:
list_of_something, nil = A.doX();
if err != nil {
    return nil, err
}

dict_by_id = A.doY();

if err != nil {
  return nil, err
}

string_split,nil = B.name.toString()

if err != nil {
  return nil, err
}

result, nill = C.postProcessResult(string_split);
if err != nil {
  return nil, err
}
return result
 
Minh ko dùng go ,tính thử . và theo vi dụ trên thì ko lẽ mỗi lần call một func hay method nao đó thì ta phải check nil hả bác

Python:
list_of_something, nil = A.doX();
if err != nil {
    return nil, err
}

dict_by_id = A.doY();

if err != nil {
  return nil, err
}

string_split,nil = B.name.toString()

if err != nil {
  return nil, err
}

result, nill = C.postProcessResult(string_split);
if err != nil {
  return nil, err
}
return result

với điều kiện cái function đó có return error hay ko nữa.

Ví dụ dict_by_id = A.doY(); có return error đâu nên ko cần check

doY() func return data, error thì mới check

Code:
dict_by_id, err = A.doY();

if err != nil {

  return nil, err

}

Có cái khuc dưới cùng thì sửa lại

return result, nil

Do function return 2 biến là result, error thì phải return đủ
 
Last edited:
Mà làm thưc tế thì cái logic handle error nó nằm ngay dưới cái call func. Nên scan code từ trên xuông dưới biết ngay cai doan handle error của thằng nào.

Quăng vô cái catch thì ko debug tốt bằng. do cái logic nó nằm xa cái thằng throw quá.

Code:
func (uh *userHandler) Login(w http.ResponseWriter, r *http.Request) (err error) {

//.....
    u, err := checkAuth(data)
    
    if err != nil {
        if err == user.ErrWrongPassword || err == user.ErrUserNotFound {
            return &ErrorAPI{
                Type:       app.ErrorTypeAuthInvalidCredentials,
                Err:        err,
                Message:    "invalid email or password",
                StatusCode: http.StatusUnauthorized,
                LogLevel:   app.LogLevelWarn,
            }
        }
        return err
    }
//...

return nil
}
 
Code:
func (uh *userHandler) Login(w http.ResponseWriter, r *http.Request) (err error) {

//.....
    u, err := checkAuth(data)
   
    if err != nil {
        if err == user.ErrWrongPassword || err == user.ErrUserNotFound {
            return &ErrorAPI{
                Type:       app.ErrorTypeAuthInvalidCredentials,
                Err:        err,
                Message:    "invalid email or password",
                StatusCode: http.StatusUnauthorized,
                LogLevel:   app.LogLevelWarn,
            }
         user_rights, err2 = user.getUserRight(u); ### vidu tiep tuc 
         if err2 != nil {
                 parsed_result, err3 = utils.parse(u, user_rights)
                  if err3 !=nil {
                     return nil, err3 
                  }
               
               } 
        }
        return err
    }
//...

return nil
}

Èo, như vi dụ này lỡ nó thành "callback hell" sao bác
 
Back
Top