Проведите код-ревью файла payer.go из сервиса платежей: компонент раз в секунду забирает из БД новые платежи и отправляет их в платёжный шлюз по HTTP, после чего помечает оплаченными. Можно предлагать любые улучшения — от именования до архитектуры.
Вопрос по ходу ревью: можем ли мы в этой реализации управлять жизненным циклом программы (запуск, остановка, корректное завершение)?
Как на собесе: 40 минут, ищи всё — гонки, утечки, ошибки, безопасность, стиль. Ссылайся на строки.
review.gogo
1packagepayer23import(4"bytes"5"database/sql"6"encoding/json"7"fmt"8"log"9"net/http"10"time"11)1213typepaymentstruct{14Idint15UserIdint16Amountfloat6417Statusstring18}1920typePayerstruct{21DB*sql.DB22URLstring23counterint24}2526funcNewPayer(db*sql.DB,urlstring)*Payer{27p:=&Payer{DB:db,URL:url}28gop.loop()29returnp30}3132func(p*Payer)loop(){33for{34rows,err:=p.DB.Query("SELECT id, user_id, amount, status FROM payments WHERE status = 'new'")35iferr!=nil{36log.Fatal(err)37}38forrows.Next(){39varpmpayment40rows.Scan(&pm.Id,&pm.UserId,&pm.Amount,&pm.Status)41gop.pay(pm)42}43time.Sleep(time.Second)44}45}4647func(p*Payer)pay(pmpayment){48body,_:=json.Marshal(pm)49resp,err:=http.Post(p.URL,"application/json",bytes.NewReader(body))50iferr!=nil{51log.Println("pay error",err)52return53}54ifresp.StatusCode!=200{55log.Println("bad status",resp.StatusCode)56}57p.DB.Exec(fmt.Sprintf("UPDATE payments SET status = 'paid' WHERE id = %d",pm.Id))58p.counter++59}6061func(p*Payer)Processed()int{62returnp.counter63}