🕵️ SicherheitslückenWhat continuous operational resilience looks like under DORA(09.09.2026 um 17:53 Uhr)
🔧 AI Nachrichten OpenAI seeks tougher AI rules. CIOs may feel the ripple effects(10.09.2026 um 12:11 Uhr)
🔧 AI Nachrichten Mistral valued at €21bn after €3bn Series D funding round(08.09.2026 um 10:19 Uhr)
🪟 Windows TippsWindows XP's Cursor Indicator Is Getting a Windows 11 Refresh(25.08.2026 um 13:00 Uhr)
🕵️ SicherheitslückenWhat continuous operational resilience looks like under DORA(09.09.2026 um 17:53 Uhr)
🔧 AI Nachrichten OpenAI seeks tougher AI rules. CIOs may feel the ripple effects(10.09.2026 um 12:11 Uhr)
🔧 AI Nachrichten Mistral valued at €21bn after €3bn Series D funding round(08.09.2026 um 10:19 Uhr)
🪟 Windows TippsWindows XP's Cursor Indicator Is Getting a Windows 11 Refresh(25.08.2026 um 13:00 Uhr)

🔧 Programmierung 🕛 vor 1 Jahr 6 Min Lesezeit
0

Circuit Breaker 🎛️ pattern with GO

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht




Problem




As Einstein said "perpetual motion machines are impossible".




Server ⚙️ can




  • Go down i.e Go Offline

  • Constantly give 500 i.e DBs they are hitting can go down

  • N number of natural causes that can make a remote server useless.



Since Client won't have any information of the Server state, it will keep on trying and all the requests are gonna be failing.






Solution






Circuit Breaker proxy for Client




  • Below is an example for it.






  • Server






    CODE
    // server.go
    package main

    import (
    "log"
    "net/http"
    "os"
    )

    // ExampleServer is a test server to check the "CircuitBreaker" pattern
    type ExampleServer struct {
    addr string
    logger *log.Logger
    isEnabled bool
    }

    // NewExampleServer creates the instance of our server
    func NewExampleServer(addr string) *ExampleServer {
    return &ExampleServer{
    addr: addr,
    logger: log.New(os.Stdout, "Server\t", log.LstdFlags),
    isEnabled: true,
    }
    }

    // ListenAndServe starts listening on the address provided
    // on creating the instance.
    func (s *ExampleServer) ListenAndServe() error {
    // The main endpoint we will request to
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    if s.isEnabled {
    s.logger.Println("responded with OK")
    w.WriteHeader(http.StatusOK)
    } else {
    s.logger.Println("responded with Error")
    w.WriteHeader(http.StatusInternalServerError)
    }
    })

    // Toggle endpoint to switch on and off responses from the main one
    http.HandleFunc("/toggle", func(w http.ResponseWriter, r *http.Request) {
    s.isEnabled = !s.isEnabled
    s.logger.Println("toggled. Is enabled:", s.isEnabled)
    w.WriteHeader(http.StatusOK)
    })

    return http.ListenAndServe(s.addr, nil)
    }







    Server.go




    • struct "ExampleServer"



    CODE
    type ExampleServer struct {
    addr string
    logger *log.Logger
    isEnabled bool
    }






    • here "isEnabled" is the server's way of saying I am online / offline.

    • when false don't send me anything at all, cause I am gonna fail them regardless.



    ExampleServer servers two routes





    • /
      -- responds with 200


    • /toggle
      -- responds with 200
      -- toggles "isEnabled" struct state.





    client.go





    CODE
    // client.go
    package main

    import (
    "errors"
    "net/http"
    )

    type NotificationClient interface {
    Send() error // We ignore all the arguments to simplify the demo
    }

    type SmsClient struct {
    baseUrl string
    }

    func NewSmsClient(baseUrl string) *SmsClient {
    return &SmsClient{
    baseUrl: baseUrl,
    }
    }

    func (s *SmsClient) Send() error {
    url := s.baseUrl + "/"
    resp, err := http.Get(url)
    if err != nil {
    return err
    }
    defer resp.Body.Close()
    if resp.StatusCode < 200 || resp.StatusCode >= 300 {
    return errors.New("bad response")
    }

    return nil
    }






    SmsClient struct has a method Send just makes an Api hit to server, return error when Api hit is not successfull.



    CODE
    func (s *SmsClient) Send() error {
    url := s.baseUrl + "/"
    resp, err := http.Get(url)
    if err != nil {
    return err
    }
    defer resp.Body.Close()
    if resp.StatusCode < 200 || resp.StatusCode >= 300 {
    return errors.New("bad response")
    }

    return nil
    }







    circuit_breaker.go





    CODE
    // circuit_breaker.go
    package main

    import (
    "log"
    "os"
    "time"

    "github.com/sony/gobreaker/v2"
    )

    type ClientCircuitBreakerProxy struct {
    client NotificationClient
    logger *log.Logger
    gb *gobreaker.CircuitBreaker[any] // downloaded lib structure
    }

    // shouldBeSwitchedToOpen checks if the circuit breaker should
    // switch to the Open state
    func shouldBeSwitchedToOpen(counts gobreaker.Counts) bool {
    failureRatio := float64(counts.TotalFailures) / float64(counts.Requests)
    return counts.Requests >= 3 && failureRatio >= 0.6
    }

    func NewClientCircuitBreakerProxy(client NotificationClient) *ClientCircuitBreakerProxy {
    logger := log.New(os.Stdout, "CB\t", log.LstdFlags)

    // We need circuit breaker configuration
    cfg := gobreaker.Settings{
    // When to flush counters int the Closed state
    Interval: 5 * time.Second,
    // Time to switch from Open to Half-open
    Timeout: 7 * time.Second,
    // Function with check when to switch from Closed to Open
    ReadyToTrip: shouldBeSwitchedToOpen,
    // set Max Request in Half Open state to 5
    MaxRequests: 5,
    // On State change Handler Fn
    OnStateChange: func(_ string, from gobreaker.State, to gobreaker.State) {
    // Handler for every state change. We'll use for debugging purpose
    logger.Println("state changed from", from.String(), "to", to.String())
    },
    }

    return &ClientCircuitBreakerProxy{
    client: client,
    logger: logger,
    gb: gobreaker.NewCircuitBreaker[any](cfg),
    }
    }

    func (c *ClientCircuitBreakerProxy) Send() error {
    // We call the Execute method and wrap our client's call
    _, err := c.gb.Execute(func() (any, error) {
    err := c.client.Send()
    return nil, err
    })
    return err
    }





    struct ClientCircuitBreakerProxy




    • holds client which can house SmsClient which we declared above.

    • holds an instance for CircuitBreaker the state machine which hold the implementation for "Circuit Breaker" pattern.



    CODE
    type ClientCircuitBreakerProxy struct {
    client NotificationClient
    logger *log.Logger
    gb *gobreaker.CircuitBreaker[any] // downloaded lib structure
    }





    In the implementation NewClientCircuitBreakerProxy fn takes a SmsClient as parameter and provides the inital values for CircuitBreaker



    CODE
        // We need circuit breaker configuration
    cfg := gobreaker.Settings{
    // When to flush counters int the Closed state
    Interval: 5 * time.Second,
    // Time to switch from Open to Half-open
    Timeout: 7 * time.Second,
    // Function with check when to switch from Closed to Open
    ReadyToTrip: shouldBeSwitchedToOpen,
    // set Max Request in Half Open state to 5
    MaxRequests: 5,
    // On State change Handler Fn
    OnStateChange: func(_ string, from gobreaker.State, to gobreaker.State) {
    // Handler for every state change. We'll use for debugging purpose
    logger.Println("state changed from", from.String(), "to", to.String())
    },
    }





    Send method in struct ClientCircuitBreakerProxy is a wrapper to client's Send method.





    main.go





    CODE
    // main.go
    package main

    import (
    "log"
    "os"
    "time"
    )

    func main() {
    logger := log.New(os.Stdout, "Main\t", log.LstdFlags)
    server := NewExampleServer(":8080")

    go func() {
    _ = server.ListenAndServe()
    }()

    var client NotificationClient

    client = NewSmsClient("http://127.0.0.1:8080")

    client = NewClientCircuitBreakerProxy(client)

    for {
    err := client.Send()
    time.Sleep(1 * time.Second)
    if err != nil {
    logger.Println("caught an error", err)
    }
    }
    }






    • create a logger with



    CODE
    logger := log.New(os.Stdout, "Main\t", log.LstdFlags)






    • start the simple go server with an run it concurrently with go routine



    CODE
    server := NewExampleServer(":8080")

    go func() {
    _ = server.ListenAndServe()
    }()






    • Initiate the Client with



    CODE

    var client NotificationClient

    client = NewSmsClient("http://127.0.0.1:8080")






    • wrap it with Circuit Breaker proxy



    CODE
        client = NewClientCircuitBreakerProxy(client)







    • run an infinity loop which makes API hits to out simple server



    CODE
        for {
    err := client.Send()
    time.Sleep(1 * time.Second)
    if err != nil {
    logger.Println("caught an error", err)
    }
    }







    Conclusion




    • As the Client makes the API hits in regular intervals to the Server

    • till an API hit /toggle Circuit will make the Circuit Breaker to be in open 🟢





    Reference



    /
















    Vollständiger Original-Bericht
    Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
    ↗ Original-Artikel auf dev.to lesen
    Wie bewertest du diesen Beitrag?
    1 Klick Feedback
    Teilen mit Netzwerk & Team:

    Community-Analysen & Experten-Meinungen 0

    Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
    Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
    Community Pulse: Relevanz-Einschätzung
    1 Klick Experten-Votum
    🔴 Akute Relevanz 0%
    🟡 In Evaluierung 0%
    🟢 Keine Auswirkung 0%
    Spannende Innovation 0%
    Verwandte Story-Cluster & Quellen (Vektor-KI)
    Port 8095 Engine
    1 Quelle
    Sam Altman calls GPT-6 Astra rollout ‘messy’ as enterprise users wait for access
    1 Quelle
    Swiss government explores replacing Microsoft 365 with open-source software
    1 Quelle
    What continuous operational resilience looks like under DORA
    Ähnliche Beiträge
    🔍 Verwandte News

    Auch interessante Nachrichten Circuit Breaker 🎛️ pattern with GO

    Thematisch verwandte Begriffe: Circuit, Breaker, pattern, with · 6 Treffer

    Laden...

    Beiträge werden geladen ...

    Laden...

    Videos werden geladen ...

    Laden...

    Beiträge werden geladen ...

    Laden...

    Videos werden geladen ...

    Laden...

    Beiträge werden geladen ...

    Laden...

    Videos werden geladen ...

    Laden...

    Beiträge werden geladen ...

    Laden...

    Videos werden geladen ...