Gin: ΠŸΡ€Π΅Ρ€Ρ‹Π²Π°Π½ΠΈΠ΅ ΠΏΡ€ΠΎΡ‚ΠΈΠ² ΠΏΠ°Π½ΠΈΠΊΠΈ

Π‘ΠΎΠ·Π΄Π°Π½Π½Ρ‹ΠΉ Π½Π° 14 июн. 2015  Β·  3ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ  Β·  Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: gin-gonic/gin

ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Ρ€Π°Π·, ΠΊΠΎΠ³Π΄Π° я Ρ…ΠΎΡ‡Ρƒ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ ΠΎΡˆΠΈΠ±ΠΊΡƒ, я Π΄ΠΎΠ»ΠΆΠ΅Π½ Π½Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ ΠΊΠΎΠ΄

if err != nil {
    c.AbortWithError(code, err)
    return
}

это ΡƒΡ€ΠΎΠ΄Π»ΠΈΠ²ΠΎ с Ρ‚Π°ΠΊΠΈΠΌ количСством return

Π― Π΄ΡƒΠΌΠ°ΡŽ, Ρ‡Ρ‚ΠΎ ΠΏΠ°Π½ΠΈΠΊΠ° ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Π»ΡƒΡ‡ΡˆΠ΅ΠΉ ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠΎΠΉ. Как Java throw Exception

if err != nil {
    panic(err) // maybe err is ErrUserNotFound
}

err опрСдСляСтся ΠΊΠ°ΠΊ

type HTTPError interface {
    HTTPStatus() int
}

ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½ΠΎΠ΅ ПО catchError, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠ΅Ρ€Π΅Ρ…Π²Π°Ρ‚ΠΈΡ‚ΡŒ ΠΎΡˆΠΈΠ±ΠΊΡƒ ΠΈ ΠΏΡ€Π΅Ρ€Π²Π°Ρ‚ΡŒ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ HTTPStatus

func catchError() gin.HandlerFunc {
    return func(c *gin.Context) {
        defer func() {
            if err := recover(); err != nil {
                switch err.(type) {
                case HTTPError:
                    e := err.(*errors.Error)
                    c.JSON(e.HTTPStatus(), e)
                    c.Abort()
                default:
                    c.AbortWithStatus(http.StatusInternalServerError)
                }
            }
        }()
        c.Next()
    }
}

ΠΌΠ½ΠΎΠ³ΠΎ нСкрасивых return ΡƒΠ΄Π°Π»Π΅Π½Ρ‹

Π‘Π°ΠΌΡ‹ΠΉ ΠΏΠΎΠ»Π΅Π·Π½Ρ‹ΠΉ ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΉ

Π‘ΠΎΠ²Π΅Ρ‚: Ρ€Π΅ΠΎΡ€Π³Π°Π½ΠΈΠ·ΡƒΠΉΡ‚Π΅ ΠΊΠΎΠ΄ Π½Π° Π±ΠΎΠ»Π΅Π΅ ΠΌΠ΅Π»ΠΊΠΈΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, поэтому вмСсто повторСния:

if err != nil {
    c.AbortWithStatus(code, error)
    return 
}

Ρ‚Ρ‹ сдСлаСшь:

func dosomething() error {
    err = dosomething1()
    if err != nil {
        return err
    }
    err = dosomething2()
    if err != nil {
        return err
    }
    err = dosomething3()
    if err != nil {
        return err
    }
}

func handler(c *gin.Context) {
    err := dosomething()
    if err != nil {
        c.AbortWithStatus(400, err)
        return;
    }
    // ...
}

ВсС 3 ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΉ

@lilee Π² настоящСС врСмя Π»ΡƒΡ‡ΡˆΠ΅ всСго:

AbortWithError()
return;

Π° Π·Π°Ρ‚Π΅ΠΌ ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½ΠΎΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎΠ΅ обСспСчСниС Ρ‡ΠΈΡ‚Π°Π΅Ρ‚ c.Errors , Ρ‡Ρ‚ΠΎΠ±Ρ‹ Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ с ошибками.

ИспользованиС panic () - плохая идСя:

  • Π­Ρ‚ΠΎ Π½Π΅ ΠΈΠ΄ΠΈΠΎΠΌΠ°Ρ‚ΠΈΠΊΠ° Go. Π’ Go panic () - строгоС ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ (ΠΈΠ»ΠΈ ΡƒΡ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠ΅). Ρ‚.Π΅. ΠΏΡ€ΠΎΠΈΠ·ΠΎΡˆΠ»ΠΎ Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ Π΄Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΏΠ»ΠΎΡ…ΠΎΠ΅ (вСроятно, ошибка).
  • Π’Ρ‹Π·ΠΎΠ² panic () выполняСтся ΠΌΠ΅Π΄Π»Π΅Π½Π½ΠΎ
  • Когда вызываСтся panic (), Π±ΠΎΠ»ΡŒΡˆΠΈΠ½ΡΡ‚Π²ΠΎ ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½ΠΎΠ³ΠΎ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎΠ³ΠΎ обСспСчСния Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ panic () ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚ 500.
  • ΠžΡ‚Π»Π°Π΄ΠΊΠ°: Π²Ρ‹ Π½Π΅ смоТСтС ΠΎΡ‚Π»ΠΈΡ‡ΠΈΡ‚ΡŒ настоящиС сбои (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π½Π΅Ρ‚ доступа ΠΊ Π½ΡƒΠ»ΡŽ) ΠΈ ошибки.

ΠšΠΎΠ½Π΅Ρ‡Π½ΠΎ, Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ всС, Ρ‡Ρ‚ΠΎ Π·Π°Ρ…ΠΎΡ‚ΠΈΡ‚Π΅, Π½ΠΎ использованиС panic () для управлСния логичСским Π½ΠΎΡ€ΠΌΠ°Π»ΡŒΠ½Ρ‹ΠΌ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠΌ - это Π°Π½Ρ‚ΠΈ-шаблон Π² Go.

Π‘ΠΎΠ²Π΅Ρ‚: Ρ€Π΅ΠΎΡ€Π³Π°Π½ΠΈΠ·ΡƒΠΉΡ‚Π΅ ΠΊΠΎΠ΄ Π½Π° Π±ΠΎΠ»Π΅Π΅ ΠΌΠ΅Π»ΠΊΠΈΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, поэтому вмСсто повторСния:

if err != nil {
    c.AbortWithStatus(code, error)
    return 
}

Ρ‚Ρ‹ сдСлаСшь:

func dosomething() error {
    err = dosomething1()
    if err != nil {
        return err
    }
    err = dosomething2()
    if err != nil {
        return err
    }
    err = dosomething3()
    if err != nil {
        return err
    }
}

func handler(c *gin.Context) {
    err := dosomething()
    if err != nil {
        c.AbortWithStatus(400, err)
        return;
    }
    // ...
}

Бпасибо за объяснСниС

Π‘Ρ‹Π»Π° Π»ΠΈ эта страница ΠΏΠΎΠ»Π΅Π·Π½ΠΎΠΉ?
0 / 5 - 0 Ρ€Π΅ΠΉΡ‚ΠΈΠ½Π³ΠΈ