Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Как не утонуть в ошибках
Search
Iskander (Alex) Sharipov
January 05, 2019
Programming
570
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Как не утонуть в ошибках
Iskander (Alex) Sharipov
January 05, 2019
More Decks by Iskander (Alex) Sharipov
See All by Iskander (Alex) Sharipov
quasigo
quasilyte
0
110
Go gamedev: XM music
quasilyte
0
160
Zero alloc pathfinding
quasilyte
0
790
Mycelium
quasilyte
0
110
Roboden game pitch
quasilyte
0
300
Ebitengine Ecosystem Overview
quasilyte
1
1k
Go gamedev patterns
quasilyte
0
560
profile-guided code analysis
quasilyte
0
390
Go inlining
quasilyte
0
180
Other Decks in Programming
See All in Programming
高専キャリア LT 発表内容
crysta1221
4
4.3k
使いながら育てる Claude Code — 開発フローの1コマンド化 × 繰り返し指摘の自動仕組み化
shiki_kakaku
1
2k
How I Won Prize Money at a Hackathon Using Codex and Symphony Alpha
yasei_no_otoko
0
130
Hono + Inertia + React で LP を構築した話
oukayuka
2
180
Cloudflare is Agents
chimame
0
180
いまどきの Codex で開発する visionOS アプリの開発スタイルについて
karad
0
170
AI時代に学ぶ 好きなルール 嫌いなルール Linter編
shorty5121
0
200
typoなんかねぇよ
raspython3
0
610
「つくるAI」だけではバグは見つからない ~テストに必要な「見つけるAI」を分離させる戦略~
mfunaki
0
200
[PyCon KR 2026] More Variants, More Diversity for AI Accelerators
achimnol
0
120
Loosening the Reins: Go Generics Get More Flexible
kuro_kurorrr
0
350
ドリフトを絶対に許さない(?)CDK運用 / CDK Ops with Zero Tolerance for Drifts (?)
akihisaikeda
1
240
Featured
See All Featured
Become a Pro
speakerdeck
PRO
31
6.2k
Building Flexible Design Systems
yeseniaperezcruz
330
41k
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.6k
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
670
エンジニアに許された特別な時間の終わり
watany
108
250k
Paper Plane
katiecoart
PRO
2
53k
How to Talk to Developers About Accessibility
jct
2
530
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
390
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
260
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
1
250
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
1
710
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
10
1.3k
Transcript
Как не утонуть в ошибках Шихалеев Илья Ведущий инженер iSpring
Напишем простой handler загрузки файла • Берем файл из запроса
• Создаем папку, куда хотим сохранить файл • Создаем итоговый файл • Записываем в итоговый файл данные из запроса 2
func uploadFile(w http.ResponseWriter, r *http.Request) { file, header := r.FormFile("file")
3
4
func uploadFile(w http.ResponseWriter, r *http.Request) { file, header, err :=
r.FormFile("file") if err != nil { http.Error(w, "Unable to read file", 400) return } 5
func uploadFile(w http.ResponseWriter, r *http.Request) { file, header, err :=
r.FormFile("file") if err != nil { http.Error(w, "Unable to read file", 400) return } os.MkdirAll("/path/", 0666) 6
7
func uploadFile(w http.ResponseWriter, r *http.Request) { file, header, err :=
r.FormFile("file") if err != nil { http.Error(w, "Unable to read file", 400) return } err = os.MkdirAll("/path/", 0666) if err != nil { http.Error(w, "Unable to create folder", 500) return } 8
resultFile := os.Create("/path/" + header.Filename) defer resultFile.Close() 9
10
resultFile, err := os.Create("/path/" + header.Filename) if err != nil
{ http.Error(w, err.Error(), 500) return } defer resultFile.Close() 11
resultFile, err := os.Create("/path/" + header.Filename) if err != nil
{ http.Error(w, err.Error(), 500) return } defer resultFile.Close() io.Copy(resultFile, file) 12
if err != nil
resultFile, err := os.Create("/path/" + header.Filename) if err != nil
{ http.Error(w, err.Error(), 500) return } defer resultFile.Close() _, err = io.Copy(resultFile, file) if err != nil { http.Error(w, err.Error(), 500) return } 14
func uploadFile(w http.ResponseWriter, r *http.Request) { file, header, err :=
r.FormFile("file") if err != nil { http.Error(w, "Unable to read file", 400) return } err = os.MkdirAll("/path/", 0666) if err != nil { http.Error(w, "Unable to create folder", 500) return } resultFile, err := os.Create("/path/" + header.Filename) if err != nil { http.Error(w, err.Error(), 500) return } defer resultFile.Close() _, err = io.Copy(resultFile, file) if err != nil { http.Error(w, err.Error(), 500) return } } 15
16
func uploadFile(w http.ResponseWriter, r *http.Request) { file, header := r.FormFile("file")
os.MkdirAll("/path/", 0666) resultFile := os.Create("/path/" + header.Filename) defer resultFile.Close() io.Copy(resultFile, file) } 17
func uploadFile(w http.ResponseWriter, r *http.Request) { file, header := r.FormFile("file")
os.MkdirAll("/path/", 0666) resultFile := os.Create("/path/" + header.Filename) defer resultFile.Close() io.Copy(resultFile, file) } if err != nil if err != nil if err != nil if err != nil if err != nil if err != nil if err != nil if err != nil if err != nil if err != nil 18
Как уменьшить дублирование и вернуться к написанию бизнес-логики? 19
Вариант 1 Решение из blog.golang.org 20
type appError struct { Error error Message string Code int
} type appHandler func(http.ResponseWriter, *http.Request) *appError func (fn appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if e := fn(w, r); e != nil { http.Error(w, e.Message, e.Code) } } func init() { http.Handle("/upload", appHandler(uploadFile)) } 21
func uploadFile(w http.ResponseWriter, r *http.Request) *appError { file, header, err
:= r.FormFile("file") if err != nil { return &appError{err, "Unable to read file", 400} } err = os.MkdirAll("/path/", 0666) if err != nil { return &appError{err, "Unable to create folder", 500} } //... 22
Вариант 2 Решение от John Cinnamond 23
type uploader struct { err error } func (u *uploader)
getFile(r *http.Request) (File, *FileHeader) { file, header, err := r.FormFile("file") return file, header } 24
type uploader struct { err error } func (u *uploader)
getFile(r *http.Request) (File, *FileHeader) { if u.err != nil { return nil, nil } file, header, err := r.FormFile("file") if err != nil { u.err = errors.Wrap(err, "Unable to read file") } return file, header } 25
func (u *uploader) mkdir(uploadDir string) { if u.err != nil
{ return } err := os.MkdirAll(uploadDir, 0666) if err != nil { u.err = errors.Wrap(err, "Unable to create folder") } } func (u *uploader) copy(dst io.Writer, src io.Reader) { if u.err != nil { return } if _, err := io.Copy(dst, src); err != nil { u.err = err } } 26
func (u *uploader) createFile(filePath string) *os.File { if u.err !=
nil { return nil } resultFile, err := os.Create(filePath) if err != nil { u.err = err } return resultFile } 27
func uploadFile(w http.ResponseWriter, r *http.Request) { u := uploader{} file,
header := u.getFile(r) u.mkdir("/path/") resultFile := u.createFile("/path/" + header.Filename) u.copy(resultFile, file) if u.err != nil { http.Error(w, fu.err.Error(), 500) return } } 28
Но как же избавиться от if err != nil? 29
Спасибо за внимание! 30
Полезные ссылки Немного про ошибки - https://golang.org/doc/effective_go.html#errors Обработка ошибок в
блоге - https://blog.golang.org/error-handling-and-go Доклад John Cinnamond - https://youtu.be/1B71SL6Y0kA Пакет errors - https://golang.org/pkg/errors/ 31