100-go-mistakes/site/pt-br/index.html
2025-04-12 20:29:18 +02:00

5431 lines
No EOL
469 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="canonical" href="https://100go.co/pt-br/">
<link rel="prev" href="../ja/">
<link rel="next" href="../book/">
<link rel="icon" href="../img/Go-Logo_LightBlue.svg">
<meta name="generator" content="mkdocs-1.5.3, mkdocs-material-9.5.11">
<title>Brazilian Portuguese Version - 100 Go Mistakes and How to Avoid Them</title>
<link rel="stylesheet" href="../assets/stylesheets/main.7e359304.min.css">
<link rel="stylesheet" href="../assets/stylesheets/palette.06af60db.min.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
<link rel="stylesheet" href="../stylesheets/extra.css">
<script>__md_scope=new URL("..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
<script id="__analytics">function __md_analytics(){function n(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],n("js",new Date),n("config","G-HMY1HYDM93"),document.addEventListener("DOMContentLoaded",function(){document.forms.search&&document.forms.search.query.addEventListener("blur",function(){this.value&&n("event","search",{search_term:this.value})}),document$.subscribe(function(){var a=document.forms.feedback;if(void 0!==a)for(var e of a.querySelectorAll("[type=submit]"))e.addEventListener("click",function(e){e.preventDefault();var t=document.location.pathname,e=this.getAttribute("data-md-value");n("event","feedback",{page:t,data:e}),a.firstElementChild.disabled=!0;e=a.querySelector(".md-feedback__note [data-md-value='"+e+"']");e&&(e.hidden=!1)}),a.hidden=!1}),location$.subscribe(function(e){n("config","G-HMY1HYDM93",{page_path:e.pathname})})});var e=document.createElement("script");e.async=!0,e.src="https://www.googletagmanager.com/gtag/js?id=G-HMY1HYDM93",document.getElementById("__analytics").insertAdjacentElement("afterEnd",e)}</script>
<script>"undefined"!=typeof __md_analytics&&__md_analytics()</script>
<meta property="og:type" content="website" >
<meta property="og:title" content="Brazilian Portuguese Version - 100 Go Mistakes and How to Avoid Them" >
<meta property="og:description" content="None" >
<meta property="og:image" content="https://100go.co/assets/images/social/pt-br.png" >
<meta property="og:image:type" content="image/png" >
<meta property="og:image:width" content="1200" >
<meta property="og:image:height" content="630" >
<meta property="og:url" content="https://100go.co/pt-br/" >
<meta name="twitter:card" content="summary_large_image" >
<meta name="twitter:title" content="Brazilian Portuguese Version - 100 Go Mistakes and How to Avoid Them" >
<meta name="twitter:description" content="None" >
<meta name="twitter:image" content="https://100go.co/assets/images/social/pt-br.png" >
<link href="../assets/stylesheets/glightbox.min.css" rel="stylesheet"/><style>
html.glightbox-open { overflow: initial; height: 100%; }
.gslide-title { margin-top: 0px; user-select: text; }
.gslide-desc { color: #666; user-select: text; }
.gslide-image img { background: white; }
.gscrollbar-fixer { padding-right: 15px; }
.gdesc-inner { font-size: 0.75rem; }
body[data-md-color-scheme="slate"] .gdesc-inner { background: var(--md-default-bg-color);}
body[data-md-color-scheme="slate"] .gslide-title { color: var(--md-default-fg-color);}
body[data-md-color-scheme="slate"] .gslide-desc { color: var(--md-default-fg-color);}</style> <script src="../assets/javascripts/glightbox.min.js"></script></head>
<body dir="ltr" data-md-color-scheme="default" data-md-color-primary="cyan" data-md-color-accent="deep-orange">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#erros-comuns-de-go" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<header class="md-header md-header--shadow md-header--lifted" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href=".." title="100 Go Mistakes and How to Avoid Them" class="md-header__button md-logo" aria-label="100 Go Mistakes and How to Avoid Them" data-md-component="logo">
<img src="../img/Go-Logo_White.svg" alt="logo">
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"/></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
100 Go Mistakes and How to Avoid Them
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Brazilian Portuguese Version
</span>
</div>
</div>
</div>
<form class="md-header__option" data-md-component="palette">
<input class="md-option" data-md-color-media="" data-md-color-scheme="default" data-md-color-primary="cyan" data-md-color-accent="deep-orange" aria-label="Switch to dark mode" type="radio" name="__palette" id="__palette_0">
<label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_1" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a4 4 0 0 0-4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0-4-4m0 10a6 6 0 0 1-6-6 6 6 0 0 1 6-6 6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12 20 8.69Z"/></svg>
</label>
<input class="md-option" data-md-color-media="" data-md-color-scheme="slate" data-md-color-primary="blue-grey" data-md-color-accent="teal" aria-label="Switch to light mode" type="radio" name="__palette" id="__palette_1">
<label class="md-header__button md-icon" title="Switch to light mode" for="__palette_0" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 18c-.89 0-1.74-.2-2.5-.55C11.56 16.5 13 14.42 13 12c0-2.42-1.44-4.5-3.5-5.45C10.26 6.2 11.11 6 12 6a6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12 20 8.69Z"/></svg>
</label>
</form>
<script>var media,input,key,value,palette=__md_get("__palette");if(palette&&palette.color){"(prefers-color-scheme)"===palette.color.media&&(media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']"),palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent"));for([key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
<div class="md-header__option">
<div class="md-select">
<button class="md-header__button md-icon" aria-label="Select language">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="m12.87 15.07-2.54-2.51.03-.03A17.52 17.52 0 0 0 14.07 6H17V4h-7V2H8v2H1v2h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04M18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12m-2.62 7 1.62-4.33L19.12 17h-3.24Z"/></svg>
</button>
<div class="md-select__inner">
<ul class="md-select__list">
<li class="md-select__item">
<a href="/" hreflang="en" class="md-select__link">
🇬🇧 English
</a>
</li>
<li class="md-select__item">
<a href="/zh/" hreflang="zh" class="md-select__link">
🇨🇳 简体中文
</a>
</li>
<li class="md-select__item">
<a href="/ja/" hreflang="ja" class="md-select__link">
🇯🇵 日本語
</a>
</li>
<li class="md-select__item">
<a href="/pt-br/" hreflang="pt-br" class="md-select__link">
🇧🇷 Português Brasileiro
</a>
</li>
</ul>
</div>
</div>
</div>
<label class="md-header__button md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
<label class="md-search__icon md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg>
</label>
<nav class="md-search__options" aria-label="Search">
<a href="javascript:void(0)" class="md-search__icon md-icon" title="Share" aria-label="Share" data-clipboard data-clipboard-text="" data-md-component="search-share" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7 0-.24-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.15c-.05.21-.08.43-.08.66 0 1.61 1.31 2.91 2.92 2.91 1.61 0 2.92-1.3 2.92-2.91A2.92 2.92 0 0 0 18 16.08Z"/></svg>
</a>
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41Z"/></svg>
</button>
</nav>
<div class="md-search__suggest" data-md-component="search-suggest"></div>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix>
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list" role="presentation"></ol>
</div>
</div>
</div>
</div>
</div>
<div class="md-header__source">
<a href="https://github.com/teivah/100-go-mistakes" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
</div>
<div class="md-source__repository">
teivah/100-go-mistakes
</div>
</a>
</div>
</nav>
<nav class="md-tabs" aria-label="Tabs" data-md-component="tabs">
<div class="md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item md-tabs__item--active">
<a href=".." class="md-tabs__link">
Go Mistakes
</a>
</li>
<li class="md-tabs__item">
<a href="../book/" class="md-tabs__link">
Book Details
</a>
</li>
<li class="md-tabs__item">
<a href="https://www.thecoder.cafe/p/100-go-mistakes" class="md-tabs__link">
The Story Behind 100 Go Mistakes and How to Avoid Them
</a>
</li>
</ul>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary md-nav--lifted" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href=".." title="100 Go Mistakes and How to Avoid Them" class="md-nav__button md-logo" aria-label="100 Go Mistakes and How to Avoid Them" data-md-component="logo">
<img src="../img/Go-Logo_White.svg" alt="logo">
</a>
100 Go Mistakes and How to Avoid Them
</label>
<div class="md-nav__source">
<a href="https://github.com/teivah/100-go-mistakes" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
</div>
<div class="md-source__repository">
teivah/100-go-mistakes
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_1" checked>
<label class="md-nav__link" for="__nav_1" id="__nav_1_label" tabindex="">
<span class="md-ellipsis">
Go Mistakes
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_1_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_1">
<span class="md-nav__icon md-icon"></span>
Go Mistakes
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href=".." class="md-nav__link">
<span class="md-ellipsis">
Common Go Mistakes
</span>
<span class="md-status md-status--new" title="New content">
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_1_2" >
<label class="md-nav__link" for="__nav_1_2" id="__nav_1_2_label" tabindex="">
<span class="md-ellipsis">
Full Sections
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_1_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_1_2">
<span class="md-nav__icon md-icon"></span>
Full Sections
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../5-interface-pollution/" class="md-nav__link">
<span class="md-ellipsis">
Interface pollution (#5)
</span>
<span class="md-status md-status--new" title="New content">
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../9-generics/" class="md-nav__link">
<span class="md-ellipsis">
Being confused about when to use generics (#9)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../20-slice/" class="md-nav__link">
<span class="md-ellipsis">
Not understanding slice length and capacity (#20)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../28-maps-memory-leaks/" class="md-nav__link">
<span class="md-ellipsis">
Maps and memory leaks (#28)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../56-concurrency-faster/" class="md-nav__link">
<span class="md-ellipsis">
Thinking concurrency is always faster (#56)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../89-benchmarks/" class="md-nav__link">
<span class="md-ellipsis">
Writing inaccurate benchmarks (#89)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../92-false-sharing/" class="md-nav__link">
<span class="md-ellipsis">
Writing concurrent code that leads to false sharing (#92)
</span>
<span class="md-status md-status--new" title="New content">
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../98-profiling-execution-tracing/" class="md-nav__link">
<span class="md-ellipsis">
Not using Go diagnostics tooling (#98)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_1_3" checked>
<label class="md-nav__link" for="__nav_1_3" id="__nav_1_3_label" tabindex="">
<span class="md-ellipsis">
Translations
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_1_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_1_3">
<span class="md-nav__icon md-icon"></span>
Translations
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../zh/" class="md-nav__link">
<span class="md-ellipsis">
🇨🇳 简体中文
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../ja/" class="md-nav__link">
<span class="md-ellipsis">
🇯🇵 日本語
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
<span class="md-ellipsis">
🇧🇷 Português Brasileiro
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
🇧🇷 Português Brasileiro
</span>
</a>
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#codigo-e-organizacao-do-projeto" class="md-nav__link">
<span class="md-ellipsis">
Código e Organização do Projeto
</span>
</a>
<nav class="md-nav" aria-label="Código e Organização do Projeto">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#sombreamento-nao-intencional-de-variavel-1" class="md-nav__link">
<span class="md-ellipsis">
Sombreamento não intencional de variável (#1)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#codigo-aninhado-desnecessario-2" class="md-nav__link">
<span class="md-ellipsis">
Código aninhado desnecessário (#2)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#uso-indevido-de-funcoes-init-3" class="md-nav__link">
<span class="md-ellipsis">
Uso indevido de funções init (#3)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#uso-excessivo-de-getters-e-setters-4" class="md-nav__link">
<span class="md-ellipsis">
Uso excessivo de getters e setters (#4)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#interface-poluidas-5" class="md-nav__link">
<span class="md-ellipsis">
Interface poluidas (#5)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#interface-do-lado-do-producer-6" class="md-nav__link">
<span class="md-ellipsis">
Interface do lado do producer (#6)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#interfaces-de-retorno-7" class="md-nav__link">
<span class="md-ellipsis">
Interfaces de retorno (#7)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#any-nao-diz-nada-8" class="md-nav__link">
<span class="md-ellipsis">
any não diz nada (#8)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#ficar-confuso-sobre-quando-usar-genericos-9" class="md-nav__link">
<span class="md-ellipsis">
Ficar confuso sobre quando usar genéricos (#9)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-estar-ciente-dos-possiveis-problemas-com-a-incorporacao-de-tipos-10" class="md-nav__link">
<span class="md-ellipsis">
Não estar ciente dos possíveis problemas com a incorporação de tipos (#10)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-usar-o-padrao-de-opcoes-funcionais-functional-options-pattern-11" class="md-nav__link">
<span class="md-ellipsis">
Não usar o padrão de opções funcionais (functional options pattern) (#11)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#desorganizacao-do-projeto-estrutura-do-projeto-e-organizacao-do-pacote-12" class="md-nav__link">
<span class="md-ellipsis">
Desorganização do projeto (estrutura do projeto e organização do pacote) (#12)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#criando-pacotes-de-utilitarios-13" class="md-nav__link">
<span class="md-ellipsis">
Criando pacotes de utilitários (#13)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#ignorando-colisoes-de-nomes-de-pacotes-14" class="md-nav__link">
<span class="md-ellipsis">
Ignorando colisões de nomes de pacotes (#14)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#documentacao-de-codigo-ausente-15" class="md-nav__link">
<span class="md-ellipsis">
Documentação de código ausente (#15)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-usando-linters-16" class="md-nav__link">
<span class="md-ellipsis">
Não usando linters (#16)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#tipos-de-dados" class="md-nav__link">
<span class="md-ellipsis">
Tipos de dados
</span>
</a>
<nav class="md-nav" aria-label="Tipos de dados">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#criando-confusao-com-literais-octais-17" class="md-nav__link">
<span class="md-ellipsis">
Criando confusão com literais octais (#17)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#negligenciando-estouros-de-numero-inteiro-18" class="md-nav__link">
<span class="md-ellipsis">
Negligenciando estouros de número inteiro (#18)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-entendendo-os-pontos-flutuantes-19" class="md-nav__link">
<span class="md-ellipsis">
Não entendendo os pontos flutuantes (#19)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-entendendo-o-comprimento-e-a-capacidade-de-slice-20" class="md-nav__link">
<span class="md-ellipsis">
Não entendendo o comprimento e a capacidade de slice (#20)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#inicializacao-de-slice-ineficiente-21" class="md-nav__link">
<span class="md-ellipsis">
Inicialização de slice ineficiente (#21)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#estar-confuso-sobre-slice-nula-vs-slice-vazia-22" class="md-nav__link">
<span class="md-ellipsis">
Estar confuso sobre slice nula vs. slice vazia (#22)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-verificar-corretamente-se-um-slice-esta-vazio-23" class="md-nav__link">
<span class="md-ellipsis">
Não verificar corretamente se um slice está vazio (#23)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-fazer-copias-de-slcies-corretamente-24" class="md-nav__link">
<span class="md-ellipsis">
Não fazer cópias de slcies corretamente (#24)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#efeitos-colaterais-inesperados-usando-o-slice-append-25" class="md-nav__link">
<span class="md-ellipsis">
Efeitos colaterais inesperados usando o slice append (#25)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#slices-e-vazamentos-de-memoria-26" class="md-nav__link">
<span class="md-ellipsis">
Slices e vazamentos de memória (#26)
</span>
</a>
<nav class="md-nav" aria-label="Slices e vazamentos de memória (#26)">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#vazamento-de-capacidade" class="md-nav__link">
<span class="md-ellipsis">
Vazamento de capacidade
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#slice-e-ponteiros" class="md-nav__link">
<span class="md-ellipsis">
Slice e ponteiros
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#inicializacao-ineficiente-do-mapa-27" class="md-nav__link">
<span class="md-ellipsis">
Inicialização ineficiente do mapa (#27)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#mapas-e-vazamentos-de-memoria-28" class="md-nav__link">
<span class="md-ellipsis">
Mapas e vazamentos de memória (#28)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#comparando-valores-incorretamente-29" class="md-nav__link">
<span class="md-ellipsis">
Comparando valores incorretamente (#29)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#estruturas-de-controle" class="md-nav__link">
<span class="md-ellipsis">
Estruturas de Controle
</span>
</a>
<nav class="md-nav" aria-label="Estruturas de Controle">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#ignorando-que-os-elementos-sao-copiados-em-loops-de-range-30" class="md-nav__link">
<span class="md-ellipsis">
Ignorando que os elementos são copiados em loops de range (#30)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#ignorando-como-os-argumentos-sao-avaliados-em-range-loops-canais-e-arrays-31" class="md-nav__link">
<span class="md-ellipsis">
Ignorando como os argumentos são avaliados em range loops (canais e arrays) (#31)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#ignorando-os-impactos-do-uso-de-elementos-ponteiros-em-range-loops-32" class="md-nav__link">
<span class="md-ellipsis">
Ignorando os impactos do uso de elementos ponteiros em range loops (#32)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#fazendo-suposicoes-erradas-durante-as-iteracoes-de-maps-ordenacao-e-insercao-do-mapa-durante-a-iteracao-33" class="md-nav__link">
<span class="md-ellipsis">
Fazendo suposições erradas durante as iterações de maps (ordenação e inserção do mapa durante a iteração) (#33)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#ignorando-como-a-declaracao-break-funciona-34" class="md-nav__link">
<span class="md-ellipsis">
Ignorando como a declaração break funciona (#34)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#usando-defer-dentro-de-um-loop-35" class="md-nav__link">
<span class="md-ellipsis">
Usando defer dentro de um loop (#35)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#strings" class="md-nav__link">
<span class="md-ellipsis">
Strings
</span>
</a>
<nav class="md-nav" aria-label="Strings">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#nao-entendendo-o-conceito-de-rune-36" class="md-nav__link">
<span class="md-ellipsis">
Não entendendo o conceito de rune (#36)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#iteracao-de-string-imprecisa-37" class="md-nav__link">
<span class="md-ellipsis">
Iteração de string imprecisa (#37)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#uso-indevido-de-funcoes-de-trim-38" class="md-nav__link">
<span class="md-ellipsis">
Uso indevido de funções de trim (#38)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#concatenacao-de-strings-subotimizada-39" class="md-nav__link">
<span class="md-ellipsis">
Concatenação de strings subotimizada (#39)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#conversoes-de-string-inuteis-40" class="md-nav__link">
<span class="md-ellipsis">
Conversões de string inúteis (#40)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#vazamentos-de-substring-e-memoria-41" class="md-nav__link">
<span class="md-ellipsis">
Vazamentos de substring e memória (#41)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#functions-and-methods" class="md-nav__link">
<span class="md-ellipsis">
Functions and Methods
</span>
</a>
<nav class="md-nav" aria-label="Functions and Methods">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#nao-saber-que-tipo-de-receptor-usar-42" class="md-nav__link">
<span class="md-ellipsis">
Não saber que tipo de receptor usar (#42)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nunca-usando-parametros-de-resultado-nomeados-43" class="md-nav__link">
<span class="md-ellipsis">
Nunca usando parâmetros de resultado nomeados (#43)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#efeitos-colaterais-nao-intencionais-com-parametros-de-resultado-nomeados-44" class="md-nav__link">
<span class="md-ellipsis">
Efeitos colaterais não intencionais com parâmetros de resultado nomeados (#44)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#retornando-um-receptor-nulo-45" class="md-nav__link">
<span class="md-ellipsis">
Retornando um receptor nulo (#45)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#usando-um-nome-de-arquivo-como-entrada-de-funcao-46" class="md-nav__link">
<span class="md-ellipsis">
Usando um nome de arquivo como entrada de função (#46)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#ignorando-como-argumentos-defer-e-receptores-sao-avaliados-avaliacao-de-argumentos-ponteiros-e-receptores-de-valor-47" class="md-nav__link">
<span class="md-ellipsis">
Ignorando como argumentos defer e receptores são avaliados (avaliação de argumentos, ponteiros e receptores de valor) (#47)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#error-management" class="md-nav__link">
<span class="md-ellipsis">
Error Management
</span>
</a>
<nav class="md-nav" aria-label="Error Management">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#panico-48" class="md-nav__link">
<span class="md-ellipsis">
Pânico (#48)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#ignorando-quando-embrulhar-um-erro-49" class="md-nav__link">
<span class="md-ellipsis">
Ignorando quando embrulhar um erro (#49)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#comparando-um-tipo-de-erro-de-forma-imprecisa-50" class="md-nav__link">
<span class="md-ellipsis">
Comparando um tipo de erro de forma imprecisa (#50)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#comparando-um-valor-de-erro-incorretamente-51" class="md-nav__link">
<span class="md-ellipsis">
Comparando um valor de erro incorretamente (#51)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#lidando-com-um-erro-duas-vezes-52" class="md-nav__link">
<span class="md-ellipsis">
Lidando com um erro duas vezes (#52)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-tratando-de-um-erro-53" class="md-nav__link">
<span class="md-ellipsis">
Não tratando de um erro (#53)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-tratando-erros-de-defer-54" class="md-nav__link">
<span class="md-ellipsis">
Não tratando erros de defer (#54)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#concurrency-foundations" class="md-nav__link">
<span class="md-ellipsis">
Concurrency: Foundations
</span>
</a>
<nav class="md-nav" aria-label="Concurrency: Foundations">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#misturando-simultaneidade-e-paralelismo-55" class="md-nav__link">
<span class="md-ellipsis">
Misturando simultaneidade e paralelismo (#55)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#pensar-que-a-simultaneidade-e-sempre-mais-rapida-56" class="md-nav__link">
<span class="md-ellipsis">
Pensar que a simultaneidade é sempre mais rápida (#56)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#ficar-confuso-sobre-quando-usar-canais-ou-mutexes-57" class="md-nav__link">
<span class="md-ellipsis">
Ficar confuso sobre quando usar canais ou mutexes (#57)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-entender-os-problemas-de-corrida-corridas-de-dados-vs-condicoes-de-corrida-e-o-modelo-de-memoria-go-58" class="md-nav__link">
<span class="md-ellipsis">
Não entender os problemas de corrida (corridas de dados vs. condições de corrida e o modelo de memória Go) (#58)
</span>
</a>
<nav class="md-nav" aria-label="Não entender os problemas de corrida (corridas de dados vs. condições de corrida e o modelo de memória Go) (#58)">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#data-race" class="md-nav__link">
<span class="md-ellipsis">
Data Race
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#race-condition" class="md-nav__link">
<span class="md-ellipsis">
Race Condition
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#nao-compreender-os-impactos-de-simultaneidade-de-um-tipo-de-carga-de-trabalho-59" class="md-nav__link">
<span class="md-ellipsis">
Não compreender os impactos de simultaneidade de um tipo de carga de trabalho (#59)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#incompreensao-dos-contextos-go-60" class="md-nav__link">
<span class="md-ellipsis">
Incompreensão dos contextos Go (#60)
</span>
</a>
<nav class="md-nav" aria-label="Incompreensão dos contextos Go (#60)">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#deadline" class="md-nav__link">
<span class="md-ellipsis">
Deadline
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#cancellation-signals" class="md-nav__link">
<span class="md-ellipsis">
Cancellation signals
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#context-values" class="md-nav__link">
<span class="md-ellipsis">
Context values
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#catching-a-context-cancellation" class="md-nav__link">
<span class="md-ellipsis">
Catching a context cancellation
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#concurrency-practice" class="md-nav__link">
<span class="md-ellipsis">
Concurrency: Practice
</span>
</a>
<nav class="md-nav" aria-label="Concurrency: Practice">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#propagando-um-contexto-improprio-61" class="md-nav__link">
<span class="md-ellipsis">
Propagando um contexto impróprio (#61)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#iniciando-uma-goroutine-sem-saber-quando-interrompe-la-62" class="md-nav__link">
<span class="md-ellipsis">
Iniciando uma goroutine sem saber quando interrompê-la (#62)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-ter-cuidado-com-goroutines-e-variaveis-de-loop-63" class="md-nav__link">
<span class="md-ellipsis">
Não ter cuidado com goroutines e variáveis de loop (#63)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#esperando-um-comportamento-deterministico-usando-selecao-e-canais-64" class="md-nav__link">
<span class="md-ellipsis">
Esperando um comportamento determinístico usando seleção e canais (#64)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-usar-canais-de-notificacao-65" class="md-nav__link">
<span class="md-ellipsis">
Não usar canais de notificação (#65)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-usar-canais-nulos-66" class="md-nav__link">
<span class="md-ellipsis">
Não usar canais nulos (#66)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#ficar-intrigado-com-o-tamanho-do-canal-67" class="md-nav__link">
<span class="md-ellipsis">
Ficar intrigado com o tamanho do canal (#67)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#esquecendo-os-possiveis-efeitos-colaterais-da-formatacao-de-strings-68" class="md-nav__link">
<span class="md-ellipsis">
Esquecendo os possíveis efeitos colaterais da formatação de strings (#68)
</span>
</a>
<nav class="md-nav" aria-label="Esquecendo os possíveis efeitos colaterais da formatação de strings (#68)">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#etcd-data-race" class="md-nav__link">
<span class="md-ellipsis">
etcd data race
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#deadlock" class="md-nav__link">
<span class="md-ellipsis">
Deadlock
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#criando-corridas-de-dados-com-acrescimo-69" class="md-nav__link">
<span class="md-ellipsis">
Criando corridas de dados com acréscimo (#69)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#usando-mutexes-imprecisamente-com-slices-e-maps-70" class="md-nav__link">
<span class="md-ellipsis">
Usando mutexes imprecisamente com slices e maps (#70)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#uso-indevido-syncwaitgroup-71" class="md-nav__link">
<span class="md-ellipsis">
Uso indevido sync.WaitGroup (#71)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#esquecendo-synccond-72" class="md-nav__link">
<span class="md-ellipsis">
Esquecendo sync.Cond (#72)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-usando-errgroup-73" class="md-nav__link">
<span class="md-ellipsis">
Não usando errgroup (#73)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#copiando-um-tipo-sync-74" class="md-nav__link">
<span class="md-ellipsis">
Copiando um tipo sync (#74)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#standard-library" class="md-nav__link">
<span class="md-ellipsis">
Standard Library
</span>
</a>
<nav class="md-nav" aria-label="Standard Library">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#fornecendo-uma-duracao-de-tempo-errada-75" class="md-nav__link">
<span class="md-ellipsis">
Fornecendo uma duração de tempo errada (#75)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#timeafter-e-vazamentos-de-memoria-76" class="md-nav__link">
<span class="md-ellipsis">
time.After e vazamentos de memória (#76)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#lidando-com-erros-comuns-json-77" class="md-nav__link">
<span class="md-ellipsis">
Lidando com erros comuns JSON (#77)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#erros-comuns-de-sql-78" class="md-nav__link">
<span class="md-ellipsis">
Erros comuns de SQL (#78)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-fechando-recursos-transitorios-body-http-sqlrows-e-osfile-79" class="md-nav__link">
<span class="md-ellipsis">
Não fechando recursos transitórios (body HTTP, sql.Rows e os.File) (#79)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#esquecendo-a-instrucao-return-apos-responder-a-uma-solicitacao-http-80" class="md-nav__link">
<span class="md-ellipsis">
Esquecendo a instrução return após responder a uma solicitação HTTP (#80)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#usando-o-cliente-e-servidor-http-padrao-81" class="md-nav__link">
<span class="md-ellipsis">
Usando o cliente e servidor HTTP padrão (#81)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#teste" class="md-nav__link">
<span class="md-ellipsis">
Teste
</span>
</a>
<nav class="md-nav" aria-label="Teste">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#nao-categorizar-testes-tags-de-construcao-variaveis-de-ambiente-e-modo-abreviado-82" class="md-nav__link">
<span class="md-ellipsis">
Não categorizar testes (tags de construção, variáveis de ambiente e modo abreviado) (#82)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-habilitando-a-bandeira-de-corrida-83" class="md-nav__link">
<span class="md-ellipsis">
Não habilitando a bandeira de corrida (#83)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-usar-modos-de-execucao-de-teste-paralelo-e-aleatorio-84" class="md-nav__link">
<span class="md-ellipsis">
Não usar modos de execução de teste (paralelo e aleatório) (#84)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-usar-testes-baseados-em-tabela-85" class="md-nav__link">
<span class="md-ellipsis">
Não usar testes baseados em tabela (#85)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#dormindo-em-testes-unitarios-86" class="md-nav__link">
<span class="md-ellipsis">
Dormindo em testes unitários (#86)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-lidar-com-a-api-de-tempo-de-forma-eficiente-87" class="md-nav__link">
<span class="md-ellipsis">
Não lidar com a API de tempo de forma eficiente (#87)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-usar-pacotes-de-utilitarios-de-teste-httptest-e-iotest-88" class="md-nav__link">
<span class="md-ellipsis">
Não usar pacotes de utilitários de teste ( httptest e iotest) (#88)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#escrevendo-benchmarks-imprecisos-89" class="md-nav__link">
<span class="md-ellipsis">
Escrevendo benchmarks imprecisos (#89)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-explorando-todos-os-recursos-de-teste-do-go-90" class="md-nav__link">
<span class="md-ellipsis">
Não explorando todos os recursos de teste do Go (#90)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-usar-fuzzing-erro-da-comunidade" class="md-nav__link">
<span class="md-ellipsis">
Não usar fuzzing (erro da comunidade)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#otimizacoes" class="md-nav__link">
<span class="md-ellipsis">
Otimizações
</span>
</a>
<nav class="md-nav" aria-label="Otimizações">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#nao-entendendo-os-caches-da-cpu-91" class="md-nav__link">
<span class="md-ellipsis">
Não entendendo os caches da CPU (#91)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#escrevendo-codigo-simultaneo-que-leva-a-compartilhamento-falso-92" class="md-nav__link">
<span class="md-ellipsis">
Escrevendo código simultâneo que leva a compartilhamento falso (#92)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-levando-em-consideracao-o-paralelismo-no-nivel-de-instrucao-93" class="md-nav__link">
<span class="md-ellipsis">
Não levando em consideração o paralelismo no nível de instrução (#93)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-estar-ciente-do-alinhamento-dos-dados-94" class="md-nav__link">
<span class="md-ellipsis">
Não estar ciente do alinhamento dos dados (#94)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-entendendo-stack-vs-heap-95" class="md-nav__link">
<span class="md-ellipsis">
Não entendendo stack vs. heap (#95)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-saber-como-reduzir-alocacoes-mudanca-de-api-otimizacoes-de-compilador-e-syncpool-96" class="md-nav__link">
<span class="md-ellipsis">
Não saber como reduzir alocações (mudança de API, otimizações de compilador e sync.Pool) (#96)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-dependendo-do-inlining-97" class="md-nav__link">
<span class="md-ellipsis">
Não dependendo do inlining (#97)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-usar-ferramentas-de-diagnostico-go-98" class="md-nav__link">
<span class="md-ellipsis">
Não usar ferramentas de diagnóstico Go (#98)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-entendendo-como-funciona-o-gc-99" class="md-nav__link">
<span class="md-ellipsis">
Não entendendo como funciona o GC (#99)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-entendendo-os-impactos-da-execucao-do-go-no-docker-e-kubernetes-100" class="md-nav__link">
<span class="md-ellipsis">
Não entendendo os impactos da execução do Go no Docker e Kubernetes (#100)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#community" class="md-nav__link">
<span class="md-ellipsis">
Community
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_2" >
<label class="md-nav__link" for="__nav_2" id="__nav_2_label" tabindex="0">
<span class="md-ellipsis">
Book Details
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2">
<span class="md-nav__icon md-icon"></span>
Book Details
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../book/" class="md-nav__link">
<span class="md-ellipsis">
100 Go Mistakes and How to Avoid Them
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../chapter-1/" class="md-nav__link">
<span class="md-ellipsis">
Read the First Chapter
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../external/" class="md-nav__link">
<span class="md-ellipsis">
External Resources
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="https://www.thecoder.cafe/p/100-go-mistakes" class="md-nav__link">
<span class="md-ellipsis">
The Story Behind 100 Go Mistakes and How to Avoid Them
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#codigo-e-organizacao-do-projeto" class="md-nav__link">
<span class="md-ellipsis">
Código e Organização do Projeto
</span>
</a>
<nav class="md-nav" aria-label="Código e Organização do Projeto">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#sombreamento-nao-intencional-de-variavel-1" class="md-nav__link">
<span class="md-ellipsis">
Sombreamento não intencional de variável (#1)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#codigo-aninhado-desnecessario-2" class="md-nav__link">
<span class="md-ellipsis">
Código aninhado desnecessário (#2)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#uso-indevido-de-funcoes-init-3" class="md-nav__link">
<span class="md-ellipsis">
Uso indevido de funções init (#3)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#uso-excessivo-de-getters-e-setters-4" class="md-nav__link">
<span class="md-ellipsis">
Uso excessivo de getters e setters (#4)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#interface-poluidas-5" class="md-nav__link">
<span class="md-ellipsis">
Interface poluidas (#5)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#interface-do-lado-do-producer-6" class="md-nav__link">
<span class="md-ellipsis">
Interface do lado do producer (#6)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#interfaces-de-retorno-7" class="md-nav__link">
<span class="md-ellipsis">
Interfaces de retorno (#7)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#any-nao-diz-nada-8" class="md-nav__link">
<span class="md-ellipsis">
any não diz nada (#8)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#ficar-confuso-sobre-quando-usar-genericos-9" class="md-nav__link">
<span class="md-ellipsis">
Ficar confuso sobre quando usar genéricos (#9)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-estar-ciente-dos-possiveis-problemas-com-a-incorporacao-de-tipos-10" class="md-nav__link">
<span class="md-ellipsis">
Não estar ciente dos possíveis problemas com a incorporação de tipos (#10)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-usar-o-padrao-de-opcoes-funcionais-functional-options-pattern-11" class="md-nav__link">
<span class="md-ellipsis">
Não usar o padrão de opções funcionais (functional options pattern) (#11)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#desorganizacao-do-projeto-estrutura-do-projeto-e-organizacao-do-pacote-12" class="md-nav__link">
<span class="md-ellipsis">
Desorganização do projeto (estrutura do projeto e organização do pacote) (#12)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#criando-pacotes-de-utilitarios-13" class="md-nav__link">
<span class="md-ellipsis">
Criando pacotes de utilitários (#13)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#ignorando-colisoes-de-nomes-de-pacotes-14" class="md-nav__link">
<span class="md-ellipsis">
Ignorando colisões de nomes de pacotes (#14)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#documentacao-de-codigo-ausente-15" class="md-nav__link">
<span class="md-ellipsis">
Documentação de código ausente (#15)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-usando-linters-16" class="md-nav__link">
<span class="md-ellipsis">
Não usando linters (#16)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#tipos-de-dados" class="md-nav__link">
<span class="md-ellipsis">
Tipos de dados
</span>
</a>
<nav class="md-nav" aria-label="Tipos de dados">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#criando-confusao-com-literais-octais-17" class="md-nav__link">
<span class="md-ellipsis">
Criando confusão com literais octais (#17)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#negligenciando-estouros-de-numero-inteiro-18" class="md-nav__link">
<span class="md-ellipsis">
Negligenciando estouros de número inteiro (#18)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-entendendo-os-pontos-flutuantes-19" class="md-nav__link">
<span class="md-ellipsis">
Não entendendo os pontos flutuantes (#19)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-entendendo-o-comprimento-e-a-capacidade-de-slice-20" class="md-nav__link">
<span class="md-ellipsis">
Não entendendo o comprimento e a capacidade de slice (#20)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#inicializacao-de-slice-ineficiente-21" class="md-nav__link">
<span class="md-ellipsis">
Inicialização de slice ineficiente (#21)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#estar-confuso-sobre-slice-nula-vs-slice-vazia-22" class="md-nav__link">
<span class="md-ellipsis">
Estar confuso sobre slice nula vs. slice vazia (#22)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-verificar-corretamente-se-um-slice-esta-vazio-23" class="md-nav__link">
<span class="md-ellipsis">
Não verificar corretamente se um slice está vazio (#23)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-fazer-copias-de-slcies-corretamente-24" class="md-nav__link">
<span class="md-ellipsis">
Não fazer cópias de slcies corretamente (#24)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#efeitos-colaterais-inesperados-usando-o-slice-append-25" class="md-nav__link">
<span class="md-ellipsis">
Efeitos colaterais inesperados usando o slice append (#25)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#slices-e-vazamentos-de-memoria-26" class="md-nav__link">
<span class="md-ellipsis">
Slices e vazamentos de memória (#26)
</span>
</a>
<nav class="md-nav" aria-label="Slices e vazamentos de memória (#26)">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#vazamento-de-capacidade" class="md-nav__link">
<span class="md-ellipsis">
Vazamento de capacidade
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#slice-e-ponteiros" class="md-nav__link">
<span class="md-ellipsis">
Slice e ponteiros
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#inicializacao-ineficiente-do-mapa-27" class="md-nav__link">
<span class="md-ellipsis">
Inicialização ineficiente do mapa (#27)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#mapas-e-vazamentos-de-memoria-28" class="md-nav__link">
<span class="md-ellipsis">
Mapas e vazamentos de memória (#28)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#comparando-valores-incorretamente-29" class="md-nav__link">
<span class="md-ellipsis">
Comparando valores incorretamente (#29)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#estruturas-de-controle" class="md-nav__link">
<span class="md-ellipsis">
Estruturas de Controle
</span>
</a>
<nav class="md-nav" aria-label="Estruturas de Controle">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#ignorando-que-os-elementos-sao-copiados-em-loops-de-range-30" class="md-nav__link">
<span class="md-ellipsis">
Ignorando que os elementos são copiados em loops de range (#30)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#ignorando-como-os-argumentos-sao-avaliados-em-range-loops-canais-e-arrays-31" class="md-nav__link">
<span class="md-ellipsis">
Ignorando como os argumentos são avaliados em range loops (canais e arrays) (#31)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#ignorando-os-impactos-do-uso-de-elementos-ponteiros-em-range-loops-32" class="md-nav__link">
<span class="md-ellipsis">
Ignorando os impactos do uso de elementos ponteiros em range loops (#32)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#fazendo-suposicoes-erradas-durante-as-iteracoes-de-maps-ordenacao-e-insercao-do-mapa-durante-a-iteracao-33" class="md-nav__link">
<span class="md-ellipsis">
Fazendo suposições erradas durante as iterações de maps (ordenação e inserção do mapa durante a iteração) (#33)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#ignorando-como-a-declaracao-break-funciona-34" class="md-nav__link">
<span class="md-ellipsis">
Ignorando como a declaração break funciona (#34)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#usando-defer-dentro-de-um-loop-35" class="md-nav__link">
<span class="md-ellipsis">
Usando defer dentro de um loop (#35)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#strings" class="md-nav__link">
<span class="md-ellipsis">
Strings
</span>
</a>
<nav class="md-nav" aria-label="Strings">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#nao-entendendo-o-conceito-de-rune-36" class="md-nav__link">
<span class="md-ellipsis">
Não entendendo o conceito de rune (#36)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#iteracao-de-string-imprecisa-37" class="md-nav__link">
<span class="md-ellipsis">
Iteração de string imprecisa (#37)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#uso-indevido-de-funcoes-de-trim-38" class="md-nav__link">
<span class="md-ellipsis">
Uso indevido de funções de trim (#38)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#concatenacao-de-strings-subotimizada-39" class="md-nav__link">
<span class="md-ellipsis">
Concatenação de strings subotimizada (#39)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#conversoes-de-string-inuteis-40" class="md-nav__link">
<span class="md-ellipsis">
Conversões de string inúteis (#40)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#vazamentos-de-substring-e-memoria-41" class="md-nav__link">
<span class="md-ellipsis">
Vazamentos de substring e memória (#41)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#functions-and-methods" class="md-nav__link">
<span class="md-ellipsis">
Functions and Methods
</span>
</a>
<nav class="md-nav" aria-label="Functions and Methods">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#nao-saber-que-tipo-de-receptor-usar-42" class="md-nav__link">
<span class="md-ellipsis">
Não saber que tipo de receptor usar (#42)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nunca-usando-parametros-de-resultado-nomeados-43" class="md-nav__link">
<span class="md-ellipsis">
Nunca usando parâmetros de resultado nomeados (#43)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#efeitos-colaterais-nao-intencionais-com-parametros-de-resultado-nomeados-44" class="md-nav__link">
<span class="md-ellipsis">
Efeitos colaterais não intencionais com parâmetros de resultado nomeados (#44)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#retornando-um-receptor-nulo-45" class="md-nav__link">
<span class="md-ellipsis">
Retornando um receptor nulo (#45)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#usando-um-nome-de-arquivo-como-entrada-de-funcao-46" class="md-nav__link">
<span class="md-ellipsis">
Usando um nome de arquivo como entrada de função (#46)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#ignorando-como-argumentos-defer-e-receptores-sao-avaliados-avaliacao-de-argumentos-ponteiros-e-receptores-de-valor-47" class="md-nav__link">
<span class="md-ellipsis">
Ignorando como argumentos defer e receptores são avaliados (avaliação de argumentos, ponteiros e receptores de valor) (#47)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#error-management" class="md-nav__link">
<span class="md-ellipsis">
Error Management
</span>
</a>
<nav class="md-nav" aria-label="Error Management">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#panico-48" class="md-nav__link">
<span class="md-ellipsis">
Pânico (#48)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#ignorando-quando-embrulhar-um-erro-49" class="md-nav__link">
<span class="md-ellipsis">
Ignorando quando embrulhar um erro (#49)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#comparando-um-tipo-de-erro-de-forma-imprecisa-50" class="md-nav__link">
<span class="md-ellipsis">
Comparando um tipo de erro de forma imprecisa (#50)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#comparando-um-valor-de-erro-incorretamente-51" class="md-nav__link">
<span class="md-ellipsis">
Comparando um valor de erro incorretamente (#51)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#lidando-com-um-erro-duas-vezes-52" class="md-nav__link">
<span class="md-ellipsis">
Lidando com um erro duas vezes (#52)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-tratando-de-um-erro-53" class="md-nav__link">
<span class="md-ellipsis">
Não tratando de um erro (#53)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-tratando-erros-de-defer-54" class="md-nav__link">
<span class="md-ellipsis">
Não tratando erros de defer (#54)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#concurrency-foundations" class="md-nav__link">
<span class="md-ellipsis">
Concurrency: Foundations
</span>
</a>
<nav class="md-nav" aria-label="Concurrency: Foundations">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#misturando-simultaneidade-e-paralelismo-55" class="md-nav__link">
<span class="md-ellipsis">
Misturando simultaneidade e paralelismo (#55)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#pensar-que-a-simultaneidade-e-sempre-mais-rapida-56" class="md-nav__link">
<span class="md-ellipsis">
Pensar que a simultaneidade é sempre mais rápida (#56)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#ficar-confuso-sobre-quando-usar-canais-ou-mutexes-57" class="md-nav__link">
<span class="md-ellipsis">
Ficar confuso sobre quando usar canais ou mutexes (#57)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-entender-os-problemas-de-corrida-corridas-de-dados-vs-condicoes-de-corrida-e-o-modelo-de-memoria-go-58" class="md-nav__link">
<span class="md-ellipsis">
Não entender os problemas de corrida (corridas de dados vs. condições de corrida e o modelo de memória Go) (#58)
</span>
</a>
<nav class="md-nav" aria-label="Não entender os problemas de corrida (corridas de dados vs. condições de corrida e o modelo de memória Go) (#58)">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#data-race" class="md-nav__link">
<span class="md-ellipsis">
Data Race
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#race-condition" class="md-nav__link">
<span class="md-ellipsis">
Race Condition
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#nao-compreender-os-impactos-de-simultaneidade-de-um-tipo-de-carga-de-trabalho-59" class="md-nav__link">
<span class="md-ellipsis">
Não compreender os impactos de simultaneidade de um tipo de carga de trabalho (#59)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#incompreensao-dos-contextos-go-60" class="md-nav__link">
<span class="md-ellipsis">
Incompreensão dos contextos Go (#60)
</span>
</a>
<nav class="md-nav" aria-label="Incompreensão dos contextos Go (#60)">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#deadline" class="md-nav__link">
<span class="md-ellipsis">
Deadline
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#cancellation-signals" class="md-nav__link">
<span class="md-ellipsis">
Cancellation signals
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#context-values" class="md-nav__link">
<span class="md-ellipsis">
Context values
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#catching-a-context-cancellation" class="md-nav__link">
<span class="md-ellipsis">
Catching a context cancellation
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#concurrency-practice" class="md-nav__link">
<span class="md-ellipsis">
Concurrency: Practice
</span>
</a>
<nav class="md-nav" aria-label="Concurrency: Practice">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#propagando-um-contexto-improprio-61" class="md-nav__link">
<span class="md-ellipsis">
Propagando um contexto impróprio (#61)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#iniciando-uma-goroutine-sem-saber-quando-interrompe-la-62" class="md-nav__link">
<span class="md-ellipsis">
Iniciando uma goroutine sem saber quando interrompê-la (#62)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-ter-cuidado-com-goroutines-e-variaveis-de-loop-63" class="md-nav__link">
<span class="md-ellipsis">
Não ter cuidado com goroutines e variáveis de loop (#63)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#esperando-um-comportamento-deterministico-usando-selecao-e-canais-64" class="md-nav__link">
<span class="md-ellipsis">
Esperando um comportamento determinístico usando seleção e canais (#64)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-usar-canais-de-notificacao-65" class="md-nav__link">
<span class="md-ellipsis">
Não usar canais de notificação (#65)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-usar-canais-nulos-66" class="md-nav__link">
<span class="md-ellipsis">
Não usar canais nulos (#66)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#ficar-intrigado-com-o-tamanho-do-canal-67" class="md-nav__link">
<span class="md-ellipsis">
Ficar intrigado com o tamanho do canal (#67)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#esquecendo-os-possiveis-efeitos-colaterais-da-formatacao-de-strings-68" class="md-nav__link">
<span class="md-ellipsis">
Esquecendo os possíveis efeitos colaterais da formatação de strings (#68)
</span>
</a>
<nav class="md-nav" aria-label="Esquecendo os possíveis efeitos colaterais da formatação de strings (#68)">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#etcd-data-race" class="md-nav__link">
<span class="md-ellipsis">
etcd data race
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#deadlock" class="md-nav__link">
<span class="md-ellipsis">
Deadlock
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#criando-corridas-de-dados-com-acrescimo-69" class="md-nav__link">
<span class="md-ellipsis">
Criando corridas de dados com acréscimo (#69)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#usando-mutexes-imprecisamente-com-slices-e-maps-70" class="md-nav__link">
<span class="md-ellipsis">
Usando mutexes imprecisamente com slices e maps (#70)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#uso-indevido-syncwaitgroup-71" class="md-nav__link">
<span class="md-ellipsis">
Uso indevido sync.WaitGroup (#71)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#esquecendo-synccond-72" class="md-nav__link">
<span class="md-ellipsis">
Esquecendo sync.Cond (#72)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-usando-errgroup-73" class="md-nav__link">
<span class="md-ellipsis">
Não usando errgroup (#73)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#copiando-um-tipo-sync-74" class="md-nav__link">
<span class="md-ellipsis">
Copiando um tipo sync (#74)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#standard-library" class="md-nav__link">
<span class="md-ellipsis">
Standard Library
</span>
</a>
<nav class="md-nav" aria-label="Standard Library">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#fornecendo-uma-duracao-de-tempo-errada-75" class="md-nav__link">
<span class="md-ellipsis">
Fornecendo uma duração de tempo errada (#75)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#timeafter-e-vazamentos-de-memoria-76" class="md-nav__link">
<span class="md-ellipsis">
time.After e vazamentos de memória (#76)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#lidando-com-erros-comuns-json-77" class="md-nav__link">
<span class="md-ellipsis">
Lidando com erros comuns JSON (#77)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#erros-comuns-de-sql-78" class="md-nav__link">
<span class="md-ellipsis">
Erros comuns de SQL (#78)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-fechando-recursos-transitorios-body-http-sqlrows-e-osfile-79" class="md-nav__link">
<span class="md-ellipsis">
Não fechando recursos transitórios (body HTTP, sql.Rows e os.File) (#79)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#esquecendo-a-instrucao-return-apos-responder-a-uma-solicitacao-http-80" class="md-nav__link">
<span class="md-ellipsis">
Esquecendo a instrução return após responder a uma solicitação HTTP (#80)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#usando-o-cliente-e-servidor-http-padrao-81" class="md-nav__link">
<span class="md-ellipsis">
Usando o cliente e servidor HTTP padrão (#81)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#teste" class="md-nav__link">
<span class="md-ellipsis">
Teste
</span>
</a>
<nav class="md-nav" aria-label="Teste">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#nao-categorizar-testes-tags-de-construcao-variaveis-de-ambiente-e-modo-abreviado-82" class="md-nav__link">
<span class="md-ellipsis">
Não categorizar testes (tags de construção, variáveis de ambiente e modo abreviado) (#82)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-habilitando-a-bandeira-de-corrida-83" class="md-nav__link">
<span class="md-ellipsis">
Não habilitando a bandeira de corrida (#83)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-usar-modos-de-execucao-de-teste-paralelo-e-aleatorio-84" class="md-nav__link">
<span class="md-ellipsis">
Não usar modos de execução de teste (paralelo e aleatório) (#84)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-usar-testes-baseados-em-tabela-85" class="md-nav__link">
<span class="md-ellipsis">
Não usar testes baseados em tabela (#85)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#dormindo-em-testes-unitarios-86" class="md-nav__link">
<span class="md-ellipsis">
Dormindo em testes unitários (#86)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-lidar-com-a-api-de-tempo-de-forma-eficiente-87" class="md-nav__link">
<span class="md-ellipsis">
Não lidar com a API de tempo de forma eficiente (#87)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-usar-pacotes-de-utilitarios-de-teste-httptest-e-iotest-88" class="md-nav__link">
<span class="md-ellipsis">
Não usar pacotes de utilitários de teste ( httptest e iotest) (#88)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#escrevendo-benchmarks-imprecisos-89" class="md-nav__link">
<span class="md-ellipsis">
Escrevendo benchmarks imprecisos (#89)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-explorando-todos-os-recursos-de-teste-do-go-90" class="md-nav__link">
<span class="md-ellipsis">
Não explorando todos os recursos de teste do Go (#90)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-usar-fuzzing-erro-da-comunidade" class="md-nav__link">
<span class="md-ellipsis">
Não usar fuzzing (erro da comunidade)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#otimizacoes" class="md-nav__link">
<span class="md-ellipsis">
Otimizações
</span>
</a>
<nav class="md-nav" aria-label="Otimizações">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#nao-entendendo-os-caches-da-cpu-91" class="md-nav__link">
<span class="md-ellipsis">
Não entendendo os caches da CPU (#91)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#escrevendo-codigo-simultaneo-que-leva-a-compartilhamento-falso-92" class="md-nav__link">
<span class="md-ellipsis">
Escrevendo código simultâneo que leva a compartilhamento falso (#92)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-levando-em-consideracao-o-paralelismo-no-nivel-de-instrucao-93" class="md-nav__link">
<span class="md-ellipsis">
Não levando em consideração o paralelismo no nível de instrução (#93)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-estar-ciente-do-alinhamento-dos-dados-94" class="md-nav__link">
<span class="md-ellipsis">
Não estar ciente do alinhamento dos dados (#94)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-entendendo-stack-vs-heap-95" class="md-nav__link">
<span class="md-ellipsis">
Não entendendo stack vs. heap (#95)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-saber-como-reduzir-alocacoes-mudanca-de-api-otimizacoes-de-compilador-e-syncpool-96" class="md-nav__link">
<span class="md-ellipsis">
Não saber como reduzir alocações (mudança de API, otimizações de compilador e sync.Pool) (#96)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-dependendo-do-inlining-97" class="md-nav__link">
<span class="md-ellipsis">
Não dependendo do inlining (#97)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-usar-ferramentas-de-diagnostico-go-98" class="md-nav__link">
<span class="md-ellipsis">
Não usar ferramentas de diagnóstico Go (#98)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-entendendo-como-funciona-o-gc-99" class="md-nav__link">
<span class="md-ellipsis">
Não entendendo como funciona o GC (#99)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#nao-entendendo-os-impactos-da-execucao-do-go-no-docker-e-kubernetes-100" class="md-nav__link">
<span class="md-ellipsis">
Não entendendo os impactos da execução do Go no Docker e Kubernetes (#100)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#community" class="md-nav__link">
<span class="md-ellipsis">
Community
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<h1 id="erros-comuns-de-go">Erros comuns de Go</h1>
<details class="tip" open="open">
<summary>The Coder Cafe</summary>
<p>Se você gostou do meu livro, talvez se interesse pelo meu novo projeto: <a href="https://thecoder.cafe?rd=100go.co/pt-br">The Coder Cafe</a>, uma newsletter diária para programadores.</p>
<blockquote>
<p>Feeling overwhelmed by the endless stream of tech content? At The Coder Cafe, we serve one essential concept for coders. Written by a senior software engineer at Google, it's perfectly brewed for your morning coffee, helping you grow your skills deeply.</p>
</blockquote>
<p><center><a href="https://thecoder.cafe?rd=100go.co/pt-br"><img src="../img/thecodercafe.png" alt="" style="width:480px;height:240px;"></a></center></p>
</details>
<p>Esta página é um resumo dos erros do <a href="../book/">100 Go Mistakes and How to Avoid Them book</a>. Enquanto isso, também está aberto à comunidade. Se você acredita que um erro comum do Go deve ser adicionado, crie uma <a href="https://github.com/teivah/100-go-mistakes/issues/new?assignees=&amp;labels=community+mistake&amp;template=community_mistake.md&amp;title=">issue</a>.</p>
<p><a class="glightbox" href="../img/inside-cover.png" data-type="image" data-width="auto" data-height="auto" data-desc-position="bottom"><img alt="" src="../img/inside-cover.png" /></a></p>
<details class="warning" open="open">
<summary>Beta</summary>
<p>Você está visualizando uma versão beta enriquecida com muito mais conteúdo. No entanto, esta versão ainda não está completa e estou procurando voluntários para me ajudar a resumir os erros restantes (<a href="https://github.com/teivah/100-go-mistakes/issues/43">GitHub issue #43</a>).</p>
<p>Progresso:
<progress value="81" max="100"/></p>
</details>
<h2 id="codigo-e-organizacao-do-projeto">Código e Organização do Projeto</h2>
<h3 id="sombreamento-nao-intencional-de-variavel-1">Sombreamento não intencional de variável (#1)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Evitar variáveis sombreadas pode ajudar a evitar erros, como fazer referência à variável errada ou confundir os desenvolvedores.</p>
</details>
<p>O sombreamento de variável ocorre quando um nome de variável é redeclarado em um bloco interno, mas essa prática está sujeita a erros. A imposição de uma regra para proibir variáveis obscuras depende do gosto pessoal. Por exemplo, às vezes pode ser conveniente reutilizar um nome de variável existente, como <code>err</code> no caso de erros. Porém, em geral, devemos ser cautelosos porque agora sabemos que podemos enfrentar um cenário onde o código compila, mas a variável que recebe o valor não é a esperada.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/1-variable-shadowing/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="codigo-aninhado-desnecessario-2">Código aninhado desnecessário (#2)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Evitar níveis aninhados e manter o caminho feliz alinhado à esquerda facilita a construção de um modelo de código mental.</p>
</details>
<p>Em geral, quanto mais níveis aninhados uma função exigir, mais complexa será sua leitura e compreensão. Vamos ver algumas aplicações diferentes desta regra para otimizar a legibilidade do nosso código:</p>
<ul>
<li>Quando um bloco <code>if</code> retorna, devemos omitir o <code>else</code> em todos os casos. Por exemplo, não deveríamos escrever:</li>
</ul>
<div class="language-go highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="k">if</span><span class="w"> </span><span class="nx">foo</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-0-2"><a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a><span class="w"> </span><span class="c1">// ...</span>
</span><span id="__span-0-3"><a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="kc">true</span>
</span><span id="__span-0-4"><a id="__codelineno-0-4" name="__codelineno-0-4" href="#__codelineno-0-4"></a><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-0-5"><a id="__codelineno-0-5" name="__codelineno-0-5" href="#__codelineno-0-5"></a><span class="w"> </span><span class="c1">// ...</span>
</span><span id="__span-0-6"><a id="__codelineno-0-6" name="__codelineno-0-6" href="#__codelineno-0-6"></a><span class="p">}</span>
</span></code></pre></div>
<p>Em vez disso, omitimos o bloco <code>else</code> assim:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-1-1"><a id="__codelineno-1-1" name="__codelineno-1-1" href="#__codelineno-1-1"></a><span class="k">if</span><span class="w"> </span><span class="nx">foo</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-1-2"><a id="__codelineno-1-2" name="__codelineno-1-2" href="#__codelineno-1-2"></a><span class="w"> </span><span class="c1">// ...</span>
</span><span id="__span-1-3"><a id="__codelineno-1-3" name="__codelineno-1-3" href="#__codelineno-1-3"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="kc">true</span>
</span><span id="__span-1-4"><a id="__codelineno-1-4" name="__codelineno-1-4" href="#__codelineno-1-4"></a><span class="p">}</span>
</span><span id="__span-1-5"><a id="__codelineno-1-5" name="__codelineno-1-5" href="#__codelineno-1-5"></a><span class="c1">// ...</span>
</span></code></pre></div>
<ul>
<li>Também podemos seguir esta lógica com um caminho não feliz:</li>
</ul>
<div class="language-go highlight"><pre><span></span><code><span id="__span-2-1"><a id="__codelineno-2-1" name="__codelineno-2-1" href="#__codelineno-2-1"></a><span class="k">if</span><span class="w"> </span><span class="nx">s</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="s">&quot;&quot;</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-2-2"><a id="__codelineno-2-2" name="__codelineno-2-2" href="#__codelineno-2-2"></a><span class="w"> </span><span class="c1">// ...</span>
</span><span id="__span-2-3"><a id="__codelineno-2-3" name="__codelineno-2-3" href="#__codelineno-2-3"></a><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-2-4"><a id="__codelineno-2-4" name="__codelineno-2-4" href="#__codelineno-2-4"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">errors</span><span class="p">.</span><span class="nx">New</span><span class="p">(</span><span class="s">&quot;empty string&quot;</span><span class="p">)</span>
</span><span id="__span-2-5"><a id="__codelineno-2-5" name="__codelineno-2-5" href="#__codelineno-2-5"></a><span class="p">}</span>
</span></code></pre></div>
<p>Aqui, um <code>s</code> vazio representa o caminho não feliz. Portanto, devemos inverter a condição assim:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-3-1"><a id="__codelineno-3-1" name="__codelineno-3-1" href="#__codelineno-3-1"></a><span class="k">if</span><span class="w"> </span><span class="nx">s</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="s">&quot;&quot;</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-3-2"><a id="__codelineno-3-2" name="__codelineno-3-2" href="#__codelineno-3-2"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">errors</span><span class="p">.</span><span class="nx">New</span><span class="p">(</span><span class="s">&quot;empty string&quot;</span><span class="p">)</span>
</span><span id="__span-3-3"><a id="__codelineno-3-3" name="__codelineno-3-3" href="#__codelineno-3-3"></a><span class="p">}</span>
</span><span id="__span-3-4"><a id="__codelineno-3-4" name="__codelineno-3-4" href="#__codelineno-3-4"></a><span class="c1">// ...</span>
</span></code></pre></div>
<p>Escrever código legível é um desafio importante para todo desenvolvedor. Esforçar-se para reduzir o número de blocos aninhados, alinhar o caminho feliz à esquerda e retornar o mais cedo possível são meios concretos para melhorar a legibilidade do nosso código.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/2-nested-code/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="uso-indevido-de-funcoes-init-3">Uso indevido de funções init (#3)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Ao inicializar variáveis, lembre-se de que as funções init têm tratamento de erros limitado e tornam o tratamento de estado e os testes mais complexos. Na maioria dos casos, as inicializações devem ser tratadas como funções específicas.</p>
</details>
<p>Uma função init é uma função usada para inicializar o estado de um aplicativo. Não aceita argumentos e não retorna nenhum resultado (uma função <code>func()</code>). Quando um pacote é inicializado, todas as declarações de constantes e variáveis do pacote são avaliadas. Então, as funções init são executadas.</p>
<p>As funções de inicialização podem levar a alguns problemas:</p>
<ul>
<li>Elas podem limitar o gerenciamento de erros.</li>
<li>Elas podem complicar a implementação de testes (por exemplo, uma dependência externa deve ser configurada, o que pode não ser necessário para o escopo dos testes unitários).</li>
<li>Se a inicialização exigir que definamos um estado, isso deverá ser feito por meio de variáveis globais.</li>
</ul>
<p>Devemos ser cautelosos com as funções init. No entanto, elas podem ser úteis em algumas situações, como na definição de configuração estática. Caso contrário, e na maioria dos casos, devemos tratar as inicializações através de funções ad hoc.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/3-init-functions/"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="uso-excessivo-de-getters-e-setters-4">Uso excessivo de getters e setters (#4)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Forcing the use of getters and setters isnt idiomatic in Go. Being pragmatic and finding the right balance between efficiency and blindly following certain idioms should be the way to go.</p>
</details>
<p>O encapsulamento de dados refere-se a ocultar os valores ou o estado de um objeto. Getters e setters são meios de habilitar o encapsulamento, fornecendo métodos exportados sobre campos de objetos não exportados.</p>
<p>No Go, não há suporte automático para getters e setters como vemos em algumas linguagens. Também não é considerado obrigatório nem idiomático o uso de getters e setters para acessar campos struct. Não devemos sobrecarregar nosso código com getters e setters em structs se eles não trouxerem nenhum valor. Deveríamos ser pragmáticos e nos esforçar para encontrar o equilíbrio certo entre eficiência e seguir expressões que às vezes são consideradas indiscutíveis em outros paradigmas de programação.</p>
<p>Lembre-se de que Go é uma linguagem única projetada para muitas características, incluindo simplicidade. No entanto, se encontrarmos necessidade de getters e setters ou, como mencionado, prevermos uma necessidade futura e ao mesmo tempo garantirmos a compatibilidade futura, não há nada de errado em usá-los.</p>
<h3 id="interface-poluidas-5">Interface poluidas (#5)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Abstrações devem ser descobertas, não criadas. Para evitar complexidade desnecessária, crie uma interface quando precisar dela e não quando você prevêr que será necessária, ou se puder pelo menos provar que a abstração é válida.</p>
</details>
<p>Leia a seção completa <a href="../5-interface-pollution/">aqui</a>.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/5-interface-pollution/"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="interface-do-lado-do-producer-6">Interface do lado do producer (#6)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Manter interfaces no lado do cliente evita abstrações desnecessárias.</p>
</details>
<p>As interfaces são satisfeitas implicitamente em Go, o que tende a ser um divisor de águas em comparação com linguagens com implementação explícita. Na maioria dos casos, a abordagem a seguir é semelhante à que descrevemos na seção anterior: <em>as abstrações devem ser descobertas, não criadas</em>. Isso significa que não cabe ao producer forçar uma determinada abstração para todos os clientes. Em vez disso, cabe ao cliente decidir se precisa de alguma forma de abstração e então determinar o melhor nível de abstração para suas necessidades.</p>
<p>Uma interface deve residir no lado do consumidor na maioria dos casos. Contudo, em contextos específicos (por exemplo, quando sabemos e não prevemos que uma abstração será útil para os consumidores), podemos querer tê-la do lado do procuder. Se o fizermos, devemos nos esforçar para mantê-lo o mínimo possível, aumentando o seu potencial de reutilização e tornando-o mais facilmente combinável.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/6-interface-producer/"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="interfaces-de-retorno-7">Interfaces de retorno (#7)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Para evitar restrições em termos de flexibilidade, uma função não deve retornar interfaces, mas implementações concretas na maioria dos casos. Por outro lado, uma função deve aceitar interfaces sempre que possível.</p>
</details>
<p>Na maioria dos casos, não devemos retornar interfaces, mas implementações concretas. Caso contrário, isso pode tornar nosso design mais complexo devido às dependências do pacote e pode restringir a flexibilidade porque todos os clientes teriam que contar com a mesma abstração. Novamente, a conclusão é semelhante às seções anteriores: se sabemos (não prevemos) que uma abstração será útil para os clientes, podemos considerar o retorno de uma interface. Caso contrário, não deveríamos forçar abstrações; eles devem ser descobertas pelos clientes. Se um cliente precisar abstrair uma implementação por qualquer motivo, ele ainda poderá fazer isso do lado do cliente.</p>
<h3 id="any-nao-diz-nada-8"><code>any</code> não diz nada (#8)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Use apenas <code>any</code> se precisar aceitar ou retornar qualquer tipo possível, como <code>json.Marshal</code>. Caso contrário, <code>any</code> não fornece informações significativas e pode levar a problemas de tempo de compilação, permitindo que um chamador chame métodos com qualquer tipo de dados.</p>
</details>
<p>O tipo <code>any</code> pode ser útil se houver uma necessidade genuína de aceitar ou retornar qualquer tipo possível (por exemplo, quando se trata de empacotamento ou formatação). Em geral, devemos evitar a todo custo generalizar demais o código que escrevemos. Talvez um pouco de código duplicado possa ocasionalmente ser melhor se melhorar outros aspectos, como a expressividade do código.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/8-any/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="ficar-confuso-sobre-quando-usar-genericos-9">Ficar confuso sobre quando usar genéricos (#9)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Depender de parâmetros genéricos e de tipo pode impedir a gravação de código clichê (boilerplate) para fatorar elementos ou comportamentos. No entanto, não use parâmetros de tipo prematuramente, mas somente quando você perceber uma necessidade concreta deles. Caso contrário, introduzem abstrações e complexidade desnecessárias.</p>
</details>
<p>Leia a seção completa <a href="../9-generics/">aqui</a>.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/9-generics/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="nao-estar-ciente-dos-possiveis-problemas-com-a-incorporacao-de-tipos-10">Não estar ciente dos possíveis problemas com a incorporação de tipos (#10)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Usar a incorporação de tipo (type embedding) também pode ajudar a evitar código clichê (boilerplate); no entanto, certifique-se de que isso não leve a problemas de visibilidade onde alguns campos deveriam ter permanecido ocultos.</p>
</details>
<p>Ao criar uma struct, Go oferece a opção de incorporar tipos. Mas isso às vezes pode levar a comportamentos inesperados se não compreendermos todas as implicações da incorporação de tipos. Ao longo desta seção, veremos como incorporar tipos, o que eles trazem e os possíveis problemas.</p>
<p>No Go, um campo struct é chamado de incorporado se for declarado sem nome. Por exemplo,</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-4-1"><a id="__codelineno-4-1" name="__codelineno-4-1" href="#__codelineno-4-1"></a><span class="kd">type</span><span class="w"> </span><span class="nx">Foo</span><span class="w"> </span><span class="kd">struct</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-4-2"><a id="__codelineno-4-2" name="__codelineno-4-2" href="#__codelineno-4-2"></a><span class="w"> </span><span class="nx">Bar</span><span class="w"> </span><span class="c1">// Embedded field</span>
</span><span id="__span-4-3"><a id="__codelineno-4-3" name="__codelineno-4-3" href="#__codelineno-4-3"></a><span class="p">}</span>
</span><span id="__span-4-4"><a id="__codelineno-4-4" name="__codelineno-4-4" href="#__codelineno-4-4"></a>
</span><span id="__span-4-5"><a id="__codelineno-4-5" name="__codelineno-4-5" href="#__codelineno-4-5"></a><span class="kd">type</span><span class="w"> </span><span class="nx">Bar</span><span class="w"> </span><span class="kd">struct</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-4-6"><a id="__codelineno-4-6" name="__codelineno-4-6" href="#__codelineno-4-6"></a><span class="w"> </span><span class="nx">Baz</span><span class="w"> </span><span class="kt">int</span>
</span><span id="__span-4-7"><a id="__codelineno-4-7" name="__codelineno-4-7" href="#__codelineno-4-7"></a><span class="p">}</span>
</span></code></pre></div>
<p>Na estrutura <code>Foo</code>, o tipo <code>Bar</code> é declarado sem nome associado; portanto, é um campo incorporado.</p>
<p>Usamos incorporação para promover os campos e métodos de um tipo incorporado. Como <code>Bar</code> contém um campo <code>Baz</code>, esse campo é promovido para <code>Foo</code>. Portanto, <code>Baz</code> fica disponível a partir de <code>Foo</code>.</p>
<p>O que podemos dizer sobre a incorporação de tipos? Primeiro, observemos que raramente é uma necessidade e significa que, qualquer que seja o caso de uso, provavelmente também poderemos resolvê-lo sem incorporação de tipo. A incorporação de tipos é usada principalmente por conveniência: na maioria dos casos, para promover comportamentos.</p>
<p>Se decidirmos usar incorporação de tipo, precisamos ter em mente duas restrições principais:</p>
<ul>
<li>Não deve ser usado apenas como um açúcar sintático para simplificar o acesso a um campo (como <code>Foo.Baz()</code> em vez de <code>Foo.Bar.Baz()</code>). Se esta for a única justificativa, não vamos incorporar o tipo interno e usar um campo.</li>
<li>Não deve promover dados (campos) ou um comportamento (métodos) que queremos ocultar do exterior: por exemplo, se permitir que os clientes acessem um comportamento de bloqueio que deve permanecer privado da struct.</li>
</ul>
<p>Usar a incorporação de tipo de forma consciente, mantendo essas restrições em mente, pode ajudar a evitar código clichê (boilerplate) com métodos de encaminhamento adicionais. No entanto, vamos garantir que não o fazemos apenas por motivos cosméticos e não promovemos elementos que deveriam permanecer ocultos.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/10-type-embedding/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="nao-usar-o-padrao-de-opcoes-funcionais-functional-options-pattern-11">Não usar o padrão de opções funcionais (functional options pattern) (#11)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Para lidar com opções de maneira conveniente e amigável à API, use o padrão de opções funcionais.</p>
</details>
<p>Embora existam diferentes implementações com pequenas variações, a ideia principal é a seguinte:</p>
<ul>
<li>Uma estrutura não exportada contém a configuração: opções.</li>
<li>Cada opção é uma função que retorna o mesmo tipo: <code>type Option func(options *options) error</code>. Por exemplo, <code>WithPort</code> aceita um argumento <code>int</code> que representa a porta e retorna um tipo <code>Option</code> que representa como atualizar a struct <code>options</code>.</li>
</ul>
<p><a class="glightbox" href="../img/options.png" data-type="image" data-width="auto" data-height="auto" data-desc-position="bottom"><img alt="" src="../img/options.png" /></a></p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-5-1"><a id="__codelineno-5-1" name="__codelineno-5-1" href="#__codelineno-5-1"></a><span class="kd">type</span><span class="w"> </span><span class="nx">options</span><span class="w"> </span><span class="kd">struct</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-5-2"><a id="__codelineno-5-2" name="__codelineno-5-2" href="#__codelineno-5-2"></a><span class="w"> </span><span class="nx">port</span><span class="w"> </span><span class="o">*</span><span class="kt">int</span>
</span><span id="__span-5-3"><a id="__codelineno-5-3" name="__codelineno-5-3" href="#__codelineno-5-3"></a><span class="p">}</span>
</span><span id="__span-5-4"><a id="__codelineno-5-4" name="__codelineno-5-4" href="#__codelineno-5-4"></a>
</span><span id="__span-5-5"><a id="__codelineno-5-5" name="__codelineno-5-5" href="#__codelineno-5-5"></a><span class="kd">type</span><span class="w"> </span><span class="nx">Option</span><span class="w"> </span><span class="kd">func</span><span class="p">(</span><span class="nx">options</span><span class="w"> </span><span class="o">*</span><span class="nx">options</span><span class="p">)</span><span class="w"> </span><span class="kt">error</span>
</span><span id="__span-5-6"><a id="__codelineno-5-6" name="__codelineno-5-6" href="#__codelineno-5-6"></a>
</span><span id="__span-5-7"><a id="__codelineno-5-7" name="__codelineno-5-7" href="#__codelineno-5-7"></a><span class="kd">func</span><span class="w"> </span><span class="nx">WithPort</span><span class="p">(</span><span class="nx">port</span><span class="w"> </span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="nx">Option</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-5-8"><a id="__codelineno-5-8" name="__codelineno-5-8" href="#__codelineno-5-8"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="kd">func</span><span class="p">(</span><span class="nx">options</span><span class="w"> </span><span class="o">*</span><span class="nx">options</span><span class="p">)</span><span class="w"> </span><span class="kt">error</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-5-9"><a id="__codelineno-5-9" name="__codelineno-5-9" href="#__codelineno-5-9"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">port</span><span class="w"> </span><span class="p">&lt;</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-5-10"><a id="__codelineno-5-10" name="__codelineno-5-10" href="#__codelineno-5-10"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">errors</span><span class="p">.</span><span class="nx">New</span><span class="p">(</span><span class="s">&quot;port should be positive&quot;</span><span class="p">)</span>
</span><span id="__span-5-11"><a id="__codelineno-5-11" name="__codelineno-5-11" href="#__codelineno-5-11"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-5-12"><a id="__codelineno-5-12" name="__codelineno-5-12" href="#__codelineno-5-12"></a><span class="w"> </span><span class="nx">options</span><span class="p">.</span><span class="nx">port</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="o">&amp;</span><span class="nx">port</span>
</span><span id="__span-5-13"><a id="__codelineno-5-13" name="__codelineno-5-13" href="#__codelineno-5-13"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="kc">nil</span>
</span><span id="__span-5-14"><a id="__codelineno-5-14" name="__codelineno-5-14" href="#__codelineno-5-14"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-5-15"><a id="__codelineno-5-15" name="__codelineno-5-15" href="#__codelineno-5-15"></a><span class="p">}</span>
</span><span id="__span-5-16"><a id="__codelineno-5-16" name="__codelineno-5-16" href="#__codelineno-5-16"></a>
</span><span id="__span-5-17"><a id="__codelineno-5-17" name="__codelineno-5-17" href="#__codelineno-5-17"></a><span class="kd">func</span><span class="w"> </span><span class="nx">NewServer</span><span class="p">(</span><span class="nx">addr</span><span class="w"> </span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="nx">opts</span><span class="w"> </span><span class="o">...</span><span class="nx">Option</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="w"> </span><span class="o">*</span><span class="nx">http</span><span class="p">.</span><span class="nx">Server</span><span class="p">,</span><span class="w"> </span><span class="kt">error</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-5-18"><a id="__codelineno-5-18" name="__codelineno-5-18" href="#__codelineno-5-18"></a><span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">options</span><span class="w"> </span><span class="nx">options</span>
</span><span id="__span-5-19"><a id="__codelineno-5-19" name="__codelineno-5-19" href="#__codelineno-5-19"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">opt</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">opts</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-5-20"><a id="__codelineno-5-20" name="__codelineno-5-20" href="#__codelineno-5-20"></a><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">opt</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">options</span><span class="p">)</span>
</span><span id="__span-5-21"><a id="__codelineno-5-21" name="__codelineno-5-21" href="#__codelineno-5-21"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-5-22"><a id="__codelineno-5-22" name="__codelineno-5-22" href="#__codelineno-5-22"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="kc">nil</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span>
</span><span id="__span-5-23"><a id="__codelineno-5-23" name="__codelineno-5-23" href="#__codelineno-5-23"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-5-24"><a id="__codelineno-5-24" name="__codelineno-5-24" href="#__codelineno-5-24"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-5-25"><a id="__codelineno-5-25" name="__codelineno-5-25" href="#__codelineno-5-25"></a>
</span><span id="__span-5-26"><a id="__codelineno-5-26" name="__codelineno-5-26" href="#__codelineno-5-26"></a><span class="w"> </span><span class="c1">// At this stage, the options struct is built and contains the config</span>
</span><span id="__span-5-27"><a id="__codelineno-5-27" name="__codelineno-5-27" href="#__codelineno-5-27"></a><span class="w"> </span><span class="c1">// Therefore, we can implement our logic related to port configuration</span>
</span><span id="__span-5-28"><a id="__codelineno-5-28" name="__codelineno-5-28" href="#__codelineno-5-28"></a><span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">port</span><span class="w"> </span><span class="kt">int</span>
</span><span id="__span-5-29"><a id="__codelineno-5-29" name="__codelineno-5-29" href="#__codelineno-5-29"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">options</span><span class="p">.</span><span class="nx">port</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-5-30"><a id="__codelineno-5-30" name="__codelineno-5-30" href="#__codelineno-5-30"></a><span class="w"> </span><span class="nx">port</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">defaultHTTPPort</span>
</span><span id="__span-5-31"><a id="__codelineno-5-31" name="__codelineno-5-31" href="#__codelineno-5-31"></a><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-5-32"><a id="__codelineno-5-32" name="__codelineno-5-32" href="#__codelineno-5-32"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="o">*</span><span class="nx">options</span><span class="p">.</span><span class="nx">port</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-5-33"><a id="__codelineno-5-33" name="__codelineno-5-33" href="#__codelineno-5-33"></a><span class="w"> </span><span class="nx">port</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">randomPort</span><span class="p">()</span>
</span><span id="__span-5-34"><a id="__codelineno-5-34" name="__codelineno-5-34" href="#__codelineno-5-34"></a><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-5-35"><a id="__codelineno-5-35" name="__codelineno-5-35" href="#__codelineno-5-35"></a><span class="w"> </span><span class="nx">port</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="o">*</span><span class="nx">options</span><span class="p">.</span><span class="nx">port</span>
</span><span id="__span-5-36"><a id="__codelineno-5-36" name="__codelineno-5-36" href="#__codelineno-5-36"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-5-37"><a id="__codelineno-5-37" name="__codelineno-5-37" href="#__codelineno-5-37"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-5-38"><a id="__codelineno-5-38" name="__codelineno-5-38" href="#__codelineno-5-38"></a>
</span><span id="__span-5-39"><a id="__codelineno-5-39" name="__codelineno-5-39" href="#__codelineno-5-39"></a><span class="w"> </span><span class="c1">// ...</span>
</span><span id="__span-5-40"><a id="__codelineno-5-40" name="__codelineno-5-40" href="#__codelineno-5-40"></a><span class="p">}</span>
</span></code></pre></div>
<p>O padrão de opções funcionais fornece uma maneira prática e amigável à API de lidar com opções. Embora o padrão do construtor possa ser uma opção válida, ele tem algumas desvantagens menores (ter que passar uma estrutura de configuração que pode estar vazia ou uma maneira menos prática de lidar com o gerenciamento de erros) que tendem a tornar o padrão de opções funcionais a maneira idiomática de lidar com esse tipo de problema no Go.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/11-functional-options/"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="desorganizacao-do-projeto-estrutura-do-projeto-e-organizacao-do-pacote-12">Desorganização do projeto (estrutura do projeto e organização do pacote) (#12)</h3>
<p>No que diz respeito à organização geral, existem diferentes escolas de pensamento. Por exemplo, devemos organizar a nossa aplicação por contexto ou por camada? Depende de nossas preferências. Podemos preferir agrupar o código por contexto (como o contexto do cliente, o contexto do contrato, etc.), ou podemos preferir seguir os princípios da arquitetura hexagonal e agrupar por camada técnica. Se a decisão que tomarmos se adequar ao nosso caso de uso, não pode ser uma decisão errada, desde que permaneçamos consistentes com ela.</p>
<p>Em relação aos pacotes, existem várias práticas recomendadas que devemos seguir. Primeiro, devemos evitar pacotes prematuros porque podem complicar demais um projeto. Às vezes, é melhor usar uma organização simples e fazer nosso projeto evoluir quando entendemos o que ele contém, em vez de nos forçarmos a fazer a estrutura perfeita desde o início. A granularidade é outra coisa essencial a considerar. Devemos evitar dezenas de pacotes nano contendo apenas um ou dois arquivos. Se o fizermos, é porque provavelmente perdemos algumas conexões lógicas entre esses pacotes, tornando nosso projeto mais difícil de ser compreendido pelos leitores. Por outro lado, também devemos evitar pacotes grandes que diluem o significado do nome de um pacote.</p>
<p>A nomenclatura dos pacotes também deve ser considerada com cuidado. Como todos sabemos (como desenvolvedores), nomear é difícil. Para ajudar os clientes a entender um projeto Go, devemos nomear nossos pacotes de acordo com o que eles fornecem, não com o que contêm. Além disso, a nomenclatura deve ser significativa. Portanto, o nome de um pacote deve ser curto, conciso, expressivo e, por convenção, uma única palavra minúscula.</p>
<p>Quanto ao que exportar, a regra é bastante simples. Devemos minimizar o que deve ser exportado tanto quanto possível para reduzir o acoplamento entre pacotes e manter ocultos os elementos exportados desnecessários. Se não tivermos certeza se devemos ou não exportar um elemento, devemos optar por não exportá-lo. Mais tarde, se descobrirmos que precisamos exportá-lo, poderemos ajustar nosso código. Vamos também ter em mente algumas exceções, como fazer com que os campos sejam exportados para que uma estrutura possa ser desempacotada com encoding/json.</p>
<p>Organizar um projeto não é simples, mas seguir essas regras deve ajudar a facilitar sua manutenção. No entanto, lembre-se de que a consistência também é vital para facilitar a manutenção. Portanto, vamos nos certificar de manter as coisas o mais consistentes possível dentro de uma base de código.</p>
<details class="note" open="open">
<summary>Note</summary>
<p>Em 2023, a equipe Go publicou uma diretriz oficial para organizar/estruturar um projeto Go: <a href="https://go.dev/doc/modules/layout">go.dev/doc/modules/layout</a></p>
</details>
<h3 id="criando-pacotes-de-utilitarios-13">Criando pacotes de utilitários (#13)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>A nomenclatura é uma parte crítica do design do aplicativo. Criar pacotes como <code>common</code>, <code>util</code> e <code>shared</code> não traz muito valor para o leitor. Refatore esses pacotes em nomes de pacotes significativos e específicos.</p>
</details>
<p>Além disso, tenha em mente que nomear um pacote com base no que ele fornece e não no que ele contém pode ser uma forma eficiente de aumentar sua expressividade.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/13-utility-packages/stringset.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="ignorando-colisoes-de-nomes-de-pacotes-14">Ignorando colisões de nomes de pacotes (#14)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Para evitar colisões de nomes entre variáveis e pacotes, levando a confusão ou talvez até bugs, use nomes exclusivos para cada um. Se isso não for viável, use um alias de importação para alterar o qualificador para diferenciar o nome do pacote do nome da variável ou pense em um nome melhor.</p>
</details>
<p>As colisões de pacotes ocorrem quando um nome de variável colide com um nome de pacote existente, impedindo que o pacote seja reutilizado. Devemos evitar colisões de nomes de variáveis para evitar ambiguidade. Se enfrentarmos uma colisão, devemos encontrar outro nome significativo ou usar um alias de importação.</p>
<h3 id="documentacao-de-codigo-ausente-15">Documentação de código ausente (#15)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Para ajudar clientes e mantenedores a entender a finalidade do seu código, documente os elementos exportados.</p>
</details>
<p>A documentação é um aspecto importante da programação. Simplifica como os clientes podem consumir uma API, mas também pode ajudar na manutenção de um projeto. No Go, devemos seguir algumas regras para tornar nosso código idiomático:</p>
<p>Primeiro, cada elemento exportado deve ser documentado. Seja uma estrutura, uma interface, uma função ou qualquer outra coisa, se for exportado deve ser documentado. A convenção é adicionar comentários, começando com o nome do elemento exportado.</p>
<p>Por convenção, cada comentário deve ser uma frase completa que termina com pontuação. Tenha também em mente que quando documentamos uma função (ou um método), devemos destacar o que a função pretende fazer, não como o faz; isso pertence ao núcleo de uma função e comentários, não à documentação. Além disso, o ideal é que a documentação forneça informações suficientes para que o consumidor não precise olhar nosso código para entender como usar um elemento exportado.</p>
<p>Quando se trata de documentar uma variável ou constante, podemos estar interessados em transmitir dois aspectos: sua finalidade e seu conteúdo. O primeiro deve funcionar como documentação de código para ser útil para clientes externos. Este último, porém, não deveria ser necessariamente público.</p>
<p>Para ajudar clientes e mantenedores a entender o escopo de um pacote, devemos também documentar cada pacote. A convenção é iniciar o comentário com <code>// Package</code> seguido do nome do pacote. A primeira linha de um comentário de pacote deve ser concisa. Isso porque ele aparecerá no pacote. Então, podemos fornecer todas as informações que precisamos nas linhas seguintes.</p>
<p>Documentar nosso código não deve ser uma restrição. Devemos aproveitar a oportunidade para garantir que isso ajude os clientes e mantenedores a entender o propósito do nosso código.</p>
<h3 id="nao-usando-linters-16">Não usando linters (#16)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Para melhorar a qualidade e consistência do código, use linters e formatadores.</p>
</details>
<p>Um linter é uma ferramenta automática para analisar código e detectar erros. O escopo desta seção não é fornecer uma lista exaustiva dos linters existentes; caso contrário, ele ficará obsoleto rapidamente. Mas devemos entender e lembrar por que os linters são essenciais para a maioria dos projetos Go.</p>
<p>No entanto, se você não é um usuário regular de linters, aqui está uma lista que você pode usar diariamente:</p>
<ul>
<li><a href="https://golang.org/cmd/vet">https://golang.org/cmd/vet</a>—A standard Go analyzer</li>
<li><a href="https://github.com/kisielk/errcheck">https://github.com/kisielk/errcheck</a>—An error checker</li>
<li><a href="https://github.com/fzipp/gocyclo">https://github.com/fzipp/gocyclo</a>—A cyclomatic complexity analyzer</li>
<li><a href="https://github.com/jgautheron/goconst">https://github.com/jgautheron/goconst</a>—A repeated string constants analyzer</li>
</ul>
<p>Além dos linters, também devemos usar formatadores de código para corrigir o estilo do código. Aqui está uma lista de alguns formatadores de código para você experimentar:</p>
<ul>
<li><a href="https://golang.org/cmd/gofmt">https://golang.org/cmd/gofmt</a>—A standard Go code formatter</li>
<li><a href="https://godoc.org/golang.org/x/tools/cmd/goimports">https://godoc.org/golang.org/x/tools/cmd/goimports</a>—A standard Go imports formatter</li>
</ul>
<p>Enquanto isso, devemos também dar uma olhada em golangci-lint (<a href="https://github.com/golangci/golangci-lint">https://github.com/golangci/golangci-lint</a>).
É uma ferramenta de linting que fornece uma fachada sobre muitos linters e formatadores úteis. Além disso, permite executar os linters em paralelo para melhorar a velocidade de análise, o que é bastante útil.</p>
<p>Linters e formatadores são uma forma poderosa de melhorar a qualidade e consistência de nossa base de código. Vamos dedicar um tempo para entender qual deles devemos usar e garantir que automatizamos sua execução (como um precommit hook de CI ou Git).</p>
<h2 id="tipos-de-dados">Tipos de dados</h2>
<h3 id="criando-confusao-com-literais-octais-17">Criando confusão com literais octais (#17)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Ao ler o código existente, lembre-se de que literais inteiros começando com <code>0</code> são números octais. Além disso, para melhorar a legibilidade, torne os inteiros octais explícitos prefixando-os com <code>0o</code>.</p>
</details>
<p>Os números octais começam com 0 (por exemplo, <code>010</code> é igual a 8 na base 10). Para melhorar a legibilidade e evitar possíveis erros para futuros leitores de código, devemos tornar os números octais explícitos usando o prefixo <code>0o</code> (por exemplo, <code>0o10</code>).</p>
<p>Devemos também observar as outras representações literais inteiras:</p>
<ul>
<li><em>Binário</em>—Usa um prefixo <code>0b</code> ou <code>0B</code>(por exemplo, <code>0b100</code> é igual a 4 na base 10)</li>
<li><em>Hexadecimal</em>—Usa um prefixo <code>0x</code> ou <code>0X</code> (por exemplo, <code>0xF</code> é igual a 15 na base 10)</li>
<li><em>Imaginário</em>—Usa um <code>i</code> sufixo (por exemplo, <code>3i</code>)</li>
</ul>
<p>Também podemos usar um caractere de sublinhado (_) como separador para facilitar a leitura. Por exemplo, podemos escrever 1 bilhão desta forma: <code>1_000_000_000</code>. Também podemos usar o caractere sublinhado com outras representações (por exemplo, <code>0b00_00_01</code>).</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/17-octal-literals/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="negligenciando-estouros-de-numero-inteiro-18">Negligenciando estouros de número inteiro (#18)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Como os overflows e underflows de números inteiros são tratados silenciosamente no Go, você pode implementar suas próprias funções para capturá-los.</p>
</details>
<p>No Go, um estouro de número inteiro que pode ser detectado em tempo de compilação gera um erro de compilação. Por exemplo,</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-6-1"><a id="__codelineno-6-1" name="__codelineno-6-1" href="#__codelineno-6-1"></a><span class="kd">var</span><span class="w"> </span><span class="nx">counter</span><span class="w"> </span><span class="kt">int32</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nx">MaxInt32</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span>
</span></code></pre></div>
<div class="language-shell highlight"><pre><span></span><code><span id="__span-7-1"><a id="__codelineno-7-1" name="__codelineno-7-1" href="#__codelineno-7-1"></a>constant<span class="w"> </span><span class="m">2147483648</span><span class="w"> </span>overflows<span class="w"> </span>int32
</span></code></pre></div>
<p>No entanto, em tempo de execução, um overflow ou underflow de inteiro é silencioso; isso não leva ao pânico do aplicativo. É essencial ter esse comportamento em mente, pois ele pode levar a bugs sorrateiros (por exemplo, um incremento de número inteiro ou adição de números inteiros positivos que leva a um resultado negativo).</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/18-integer-overflows"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="nao-entendendo-os-pontos-flutuantes-19">Não entendendo os pontos flutuantes (#19)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Fazer comparações de ponto flutuante dentro de um determinado delta pode garantir que seu código seja portátil. Ao realizar adição ou subtração, agrupe as operações com ordem de grandeza semelhante para favorecer a precisão. Além disso, execute multiplicação e divisão antes da adição e subtração.</p>
</details>
<p>Em Go, existem dois tipos de ponto flutuante (se omitirmos os números imaginários): float32 e float64. O conceito de ponto flutuante foi inventado para resolver o principal problema dos números inteiros: sua incapacidade de representar valores fracionários. Para evitar surpresas desagradáveis, precisamos saber que a aritmética de ponto flutuante é uma aproximação da aritmética real.</p>
<p>Para isso, veremos um exemplo de multiplicação:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-8-1"><a id="__codelineno-8-1" name="__codelineno-8-1" href="#__codelineno-8-1"></a><span class="kd">var</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="kt">float32</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mf">1.0001</span>
</span><span id="__span-8-2"><a id="__codelineno-8-2" name="__codelineno-8-2" href="#__codelineno-8-2"></a><span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="nx">n</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">n</span><span class="p">)</span>
</span></code></pre></div>
<p>Podemos esperar que este código imprima o resultado de 1.0001 * 1.0001 = 1,00020001, certo? No entanto, executá-lo na maioria dos processadores x86 imprime 1.0002.</p>
<p>Como os tipos <code>float32</code> e <code>float64</code> em Go são aproximações, temos que ter algumas regras em mente:</p>
<ul>
<li>Ao comparar dois números de ponto flutuante, verifique se a diferença está dentro de um intervalo aceitável.</li>
<li>Ao realizar adições ou subtrações, agrupe operações com ordem de magnitude semelhante para melhor precisão.</li>
<li>Para favorecer a precisão, se uma sequência de operações exigir adição, subtração, multiplicação ou divisão, execute primeiro as operações de multiplicação e divisão.</li>
</ul>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/19-floating-points/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="nao-entendendo-o-comprimento-e-a-capacidade-de-slice-20">Não entendendo o comprimento e a capacidade de slice (#20)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Compreender a diferença entre comprimento e capacidade da slice deve fazer parte do conhecimento básico de um desenvolvedor Go. O comprimento de slice é o número de elementos disponíveis na slice, enquanto a capacidade de slice é o número de elementos na matriz de apoio.</p>
</details>
<p>Leia a seção completa <a href="../20-slice/">aqui</a>.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/20-slice-length-cap/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="inicializacao-de-slice-ineficiente-21">Inicialização de slice ineficiente (#21)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Ao criar uma fatia, inicialize-a com um determinado comprimento ou capacidade se o seu comprimento já for conhecido. Isso reduz o número de alocações e melhora o desempenho.</p>
</details>
<p>Ao inicializar uma fatia usando <code>make</code>, podemos fornecer um comprimento e uma capacidade opcional. Esquecer de passar um valor apropriado para ambos os parâmetros quando faz sentido é um erro generalizado. Na verdade, isso pode levar a múltiplas cópias e esforço adicional para o <abbr title="Garbage Collector">GC</abbr> limpar as matrizes de apoio temporárias. Em termos de desempenho, não há uma boa razão para não ajudar o tempo de execução do Go.</p>
<p>Nossas opções são alocar uma fatia com determinada capacidade ou comprimento. Destas duas soluções, vimos que a segunda tende a ser um pouco mais rápida. Mas usar uma determinada capacidade e anexar pode ser mais fácil de implementar e ler em alguns contextos.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/21-slice-init/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="estar-confuso-sobre-slice-nula-vs-slice-vazia-22">Estar confuso sobre slice nula vs. slice vazia (#22)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>To prevent common confusions such as when using the <code>encoding/json</code> or the <code>reflect</code> package, you need to understand the difference between nil and empty slices. Both are zero-length, zero-capacity slices, but only a nil slice doesnt require allocation.</p>
</details>
<p>No Go, há uma distinção entre slices nulas e vazias. Uma slice nula é igual a <code>nil</code>, enquanto uma slice vazia tem comprimento zero. Uma slice nula está vazia, mas uma slice vazia não é necessariamente <code>nil</code>. Enquanto isso, uma slice nula não requer nenhuma alocação. Vimos ao longo desta seção como inicializar uma slice dependendo do contexto usando</p>
<ul>
<li><code>var s []string</code> se não tivermos certeza sobre o comprimento final e a fatia pode estar vazia</li>
<li><code>[]string(nil)</code> como açúcar sintático para criar uma fatia nula e vazia</li>
<li><code>make([]string, length)</code> se o comprimento futuro for conhecido</li>
</ul>
<p>A última opção, <code>[]string{}</code> deve ser evitada se inicializarmos a fatia sem elementos. Finalmente, vamos verificar se as bibliotecas que usamos fazem distinções entre fatias nulas e vazias para evitar comportamentos inesperados.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/22-nil-empty-slice/"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="nao-verificar-corretamente-se-um-slice-esta-vazio-23">Não verificar corretamente se um slice está vazio (#23)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Para verificar se uma fatia não contém nenhum elemento, verifique seu comprimento. Esta verificação funciona independentemente de o slice estar <code>nil</code> ou vazio. O mesmo vale para maps. Para projetar APIs inequívocas, você não deve distinguir entre slice nulos e vazios.</p>
</details>
<p>Para determinar se um slice possui elementos, podemos fazê-lo verificando se o slice é nulo ou se seu comprimento é igual a 0. Verificar o comprimento é a melhor opção a seguir, pois cobrirá ambos se o slice estiver vazio ou se o slice é nulo.</p>
<p>Enquanto isso, ao projetar interfaces, devemos evitar distinguir slices nulos e vazios, o que leva a erros sutis de programação. Ao retornar slices, não deve haver diferença semântica nem técnica se retornarmos um slice nulo ou vazio. Ambos devem significar a mesma coisa para quem liga. Este princípio é o mesmo com maps. Para verificar se um map está vazio, verifique seu comprimento, não se é nulo.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/23-checking-slice-empty/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="nao-fazer-copias-de-slcies-corretamente-24">Não fazer cópias de slcies corretamente (#24)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Para copiar um slice para outro usando a função <code>copy</code>, lembre-se que o número de elementos copiados corresponde ao mínimo entre os comprimentos dos dois slices.</p>
</details>
<p>Copiar elementos de um slice para outro é uma operação razoavelmente frequente. Ao utilizar a cópia, devemos lembrar que o número de elementos copiados para o destino corresponde ao mínimo entre os comprimentos dos dois slices. Tenha também em mente que existem outras alternativas para copiar um slice, por isso não devemos nos surpreender se as encontrarmos em uma base de código.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/24-slice-copy/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="efeitos-colaterais-inesperados-usando-o-slice-append-25">Efeitos colaterais inesperados usando o slice append (#25)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Usar <code>copy</code> ou a expressão de slice completa é uma forma de evitar que <code>append</code> crie conflitos se duas funções diferentes usarem slices apoiados pela mesmo array. No entanto, apenas uma cópia de slice evita vazamentos de memória se você quiser reduzir um slice grande.</p>
</details>
<p>Ao usar o slicing, devemos lembrar que podemos enfrentar uma situação que leva a efeitos colaterais não intencionais. Se o slice resultante tiver um comprimento menor que sua capacidade, o acréscimo poderá alterar o slice original. Se quisermos restringir a gama de possíveis efeitos colaterais, podemos usar uma cópia de slice ou a expressão de slice completa, o que nos impede de fazer uma cópia.</p>
<details class="note" open="open">
<summary>Note</summary>
<p><code>s[low:high:max]</code>(expressão de slice completo): Esta instrução cria um slice semelhante àquele criado com <code>s[low:high]</code>, exceto que a capacidade de slice resultante é igual a <code>max - low</code>.</p>
</details>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/25-slice-append/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="slices-e-vazamentos-de-memoria-26">Slices e vazamentos de memória (#26)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Trabalhando com um slice de ponteiros ou estruturas com campos de ponteiro, você pode evitar vazamentos de memória marcando como nulos os elementos excluídos por uma operação de fatiamento.</p>
</details>
<h4 id="vazamento-de-capacidade">Vazamento de capacidade</h4>
<p>Lembre-se de que fatiar um slice ou array grande pode levar a um potencial alto consumo de memória. O espaço restante não será recuperado pelo <abbr title="Garbage Collector">GC</abbr> e podemos manter um grande array de apoio, apesar de usarmos apenas alguns elementos. Usar uma cópia em slice é a solução para evitar tal caso.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/26-slice-memory-leak/capacity-leak"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h4 id="slice-e-ponteiros">Slice e ponteiros</h4>
<p>Quando usamos a operação de fatiamento com ponteiros ou estruturas com campos de ponteiro, precisamos saber que o <abbr title="Garbage Collector">GC</abbr> não recuperará esses elementos. Nesse caso, as duas opções são realizar uma cópia ou marcar explicitamente os elementos restantes ou seus campos como <code>nil</code>.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/26-slice-memory-leak/slice-pointers"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="inicializacao-ineficiente-do-mapa-27">Inicialização ineficiente do mapa (#27)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Ao criar um mapa, inicialize-o com um determinado comprimento se o seu comprimento já for conhecido. Isso reduz o número de alocações e melhora o desempenho.</p>
</details>
<p>Um mapa fornece uma coleção não ordenada de pares chave-valor em que todas as chaves são distintas. No Go, um mapa é baseado na estrutura de dados da tabela hash. Internamente, uma tabela hash é uma matriz de intervalos e cada intervalo é um ponteiro para uma matriz de pares de valores-chave.</p>
<p>Se soubermos de antemão o número de elementos que um mapa conterá, devemos criá-lo fornecendo um tamanho inicial. Fazer isso evita o crescimento potencial do mapa, o que é bastante pesado em termos de computação porque requer a realocação de espaço suficiente e o reequilíbrio de todos os elementos.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/27-map-init/main_test.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="mapas-e-vazamentos-de-memoria-28">Mapas e vazamentos de memória (#28)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Um mapa sempre pode crescer na memória, mas nunca diminui. Portanto, se isso causar alguns problemas de memória, você pode tentar diferentes opções, como forçar Go a recriar o mapa ou usar ponteiros.</p>
</details>
<p>Leia a seção completa <a href="../28-maps-memory-leaks/">aqui</a>.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/28-map-memory-leak/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="comparando-valores-incorretamente-29">Comparando valores incorretamente (#29)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Para comparar tipos em Go, você pode usar os operadores == e != se dois tipos forem comparáveis: booleanos, numerais, strings, ponteiros, canais e estruturas são compostos inteiramente de tipos comparáveis. Caso contrário, você pode usar <code>reflect.DeepEquale</code> pagar o preço da reflexão ou usar implementações e bibliotecas personalizadas.</p>
</details>
<p>É essencial entender como usar <code>==</code> e <code>!=</code> para fazer comparações de forma eficaz. Podemos usar esses operadores em operandos comparáveis:</p>
<ul>
<li><em>Booleans</em>—Compara se dois booleanos são iguais.</li>
<li><em>Numerics (int, float, and complex types)</em>—Compare se dois números são iguais.</li>
<li><em>Strings</em>—Compare se duas strings são iguais.</li>
<li><em>Channels</em>—Compare se dois canais foram criados pela mesma chamada a ser feita ou se ambos são nulos.</li>
<li><em>Interfaces</em>—Compare se duas interfaces têm tipos dinâmicos idênticos e valores dinâmicos iguais ou se ambas são nulas.</li>
<li><em>Pointers</em>—Compare se dois ponteiros apontam para o mesmo valor na memória ou se ambos são nulos.</li>
<li><em>Structs and arrays</em>—Compare se são compostas de tipos semelhantes.</li>
</ul>
<details class="note" open="open">
<summary>Note</summary>
<p>Também podemos usar os operadores <code>?</code>, <code>&gt;=</code>, <code>&lt;</code> e <code>&gt;</code> com tipos numéricos para comparar valores e com strings para comparar sua ordem lexical.</p>
</details>
<p>Se os operandos não forem comparáveis (por exemplo, slices e mapas), teremos que usar outras opções, como reflexão. A reflexão é uma forma de metaprogramação e se refere à capacidade de um aplicativo de introspectar e modificar sua estrutura e comportamento. Por exemplo, em Go, podemos usar <code>reflect.DeepEqual</code>. Esta função informa se dois elementos são profundamente iguais percorrendo recursivamente dois valores. Os elementos que ele aceita são tipos básicos mais arrays, estruturas, slices, mapas, ponteiros, interfaces e funções. No entanto, o principal problema é a penalidade de desempenho.</p>
<p>Se o desempenho for crucial em tempo de execução, implementar nosso método customizado pode ser a melhor solução. Uma observação adicional: devemos lembrar que a biblioteca padrão possui alguns métodos de comparação existentes. Por exemplo, podemos usar a função <code>bytes.Compare</code> otimizada para comparar duas slices de bytes. Antes de implementar um método customizado, precisamos ter certeza de não reinventar a roda.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/29-comparing-values/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h2 id="estruturas-de-controle">Estruturas de Controle</h2>
<h3 id="ignorando-que-os-elementos-sao-copiados-em-loops-de-range-30">Ignorando que os elementos são copiados em loops de <code>range</code> (#30)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>O elemento de valor em um loop de <code>range</code> é uma cópia. Portanto, para modificar uma struct, por exemplo, acesse-a através de seu índice ou através de um loop <code>for</code> clássico (a menos que o elemento ou campo que você deseja modificar seja um ponteiro).</p>
</details>
<p>Um range loop permite iterar em diferentes estruturas de dados:</p>
<ul>
<li>String</li>
<li>Array</li>
<li>Pointer to an array</li>
<li>Slice</li>
<li>Map</li>
<li>Receiving channel</li>
</ul>
<p>Comparado a um for <code>loop</code> clássico, um loop <code>range</code> é uma maneira conveniente de iterar todos os elementos de uma dessas estruturas de dados, graças à sua sintaxe concisa.</p>
<p>Ainda assim, devemos lembrar que o elemento de valor em um range loop é uma cópia. Portanto, se o valor for uma estrutura que precisamos sofrer mutação, atualizaremos apenas a cópia, não o elemento em si, a menos que o valor ou campo que modificamos seja um ponteiro. As opções preferidas são acessar o elemento através do índice usando um range loop ou um loop for clássico.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/30-range-loop-element-copied/"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="ignorando-como-os-argumentos-sao-avaliados-em-range-loops-canais-e-arrays-31">Ignorando como os argumentos são avaliados em range loops (canais e arrays) (#31)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Entender que a expressão passada ao operador <code>range</code> é avaliada apenas uma vez antes do início do loop pode ajudar a evitar erros comuns, como atribuição ineficiente em canal ou iteração de slice.</p>
</details>
<p>O range loop avalia a expressão fornecida apenas uma vez, antes do início do loop, fazendo uma cópia (independentemente do tipo). Devemos lembrar deste comportamento para evitar erros comuns que podem, por exemplo, nos levar a acessar o elemento errado. Por exemplo:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-9-1"><a id="__codelineno-9-1" name="__codelineno-9-1" href="#__codelineno-9-1"></a><span class="nx">a</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="p">[</span><span class="mi">3</span><span class="p">]</span><span class="kt">int</span><span class="p">{</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">}</span>
</span><span id="__span-9-2"><a id="__codelineno-9-2" name="__codelineno-9-2" href="#__codelineno-9-2"></a><span class="k">for</span><span class="w"> </span><span class="nx">i</span><span class="p">,</span><span class="w"> </span><span class="nx">v</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">a</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-9-3"><a id="__codelineno-9-3" name="__codelineno-9-3" href="#__codelineno-9-3"></a><span class="w"> </span><span class="nx">a</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mi">10</span>
</span><span id="__span-9-4"><a id="__codelineno-9-4" name="__codelineno-9-4" href="#__codelineno-9-4"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-9-5"><a id="__codelineno-9-5" name="__codelineno-9-5" href="#__codelineno-9-5"></a><span class="w"> </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="nx">v</span><span class="p">)</span>
</span><span id="__span-9-6"><a id="__codelineno-9-6" name="__codelineno-9-6" href="#__codelineno-9-6"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-9-7"><a id="__codelineno-9-7" name="__codelineno-9-7" href="#__codelineno-9-7"></a><span class="p">}</span>
</span></code></pre></div>
<p>Este código atualiza o último índice para 10. No entanto, se executarmos este código, ele não imprimirá 10; imprime 2.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/31-range-loop-arg-evaluation/"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="ignorando-os-impactos-do-uso-de-elementos-ponteiros-em-range-loops-32"><img alt="⚠" class="twemoji" src="https://cdn.jsdelivr.net/gh/jdecked/twemoji@15.0.3/assets/svg/26a0.svg" title=":warning:" /> Ignorando os impactos do uso de elementos ponteiros em <code>range</code> loops (#32)</h3>
<details class="warning" open="open">
<summary>Warning</summary>
<p>Este erro não é mais relevante no Go 1.22 (<a href="https://go.dev/blog/loopvar-preview">detalhes</a>).</p>
</details>
<h3 id="fazendo-suposicoes-erradas-durante-as-iteracoes-de-maps-ordenacao-e-insercao-do-mapa-durante-a-iteracao-33">Fazendo suposições erradas durante as iterações de maps (ordenação e inserção do mapa durante a iteração) (#33)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Para garantir resultados previsíveis ao usar maps, lembre-se de que uma estrutura de dados de mapa:</p>
</details>
<ul>
<li>Não ordena os dados por chaves</li>
<li>Não preserva o pedido de inserção</li>
<li>Não tem uma ordem de iteração determinística</li>
<li>Não garante que um elemento adicionado durante uma iteração será produzido durante esta iteração</li>
</ul>
<!-- TODO -->
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/33-map-iteration/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="ignorando-como-a-declaracao-break-funciona-34">Ignorando como a declaração <code>break</code> funciona (#34)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Usar <code>break</code> ou <code>continue</code> com um rótulo impõe a quebra de uma instrução específica. Isso pode ser útil com instruções <code>switch</code> ou <code>select</code> dentro de loops.</p>
</details>
<p>Uma instrução break é comumente usada para encerrar a execução de um loop. Quando loops são usados em conjunto com switch ou select, os desenvolvedores frequentemente cometem o erro de quebrar a instrução errada. Por exemplo:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-10-1"><a id="__codelineno-10-1" name="__codelineno-10-1" href="#__codelineno-10-1"></a><span class="k">for</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="p">&lt;</span><span class="w"> </span><span class="mi">5</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-10-2"><a id="__codelineno-10-2" name="__codelineno-10-2" href="#__codelineno-10-2"></a><span class="w"> </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%d &quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="p">)</span>
</span><span id="__span-10-3"><a id="__codelineno-10-3" name="__codelineno-10-3" href="#__codelineno-10-3"></a>
</span><span id="__span-10-4"><a id="__codelineno-10-4" name="__codelineno-10-4" href="#__codelineno-10-4"></a><span class="w"> </span><span class="k">switch</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-10-5"><a id="__codelineno-10-5" name="__codelineno-10-5" href="#__codelineno-10-5"></a><span class="w"> </span><span class="k">default</span><span class="p">:</span>
</span><span id="__span-10-6"><a id="__codelineno-10-6" name="__codelineno-10-6" href="#__codelineno-10-6"></a><span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="mi">2</span><span class="p">:</span>
</span><span id="__span-10-7"><a id="__codelineno-10-7" name="__codelineno-10-7" href="#__codelineno-10-7"></a><span class="w"> </span><span class="k">break</span>
</span><span id="__span-10-8"><a id="__codelineno-10-8" name="__codelineno-10-8" href="#__codelineno-10-8"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-10-9"><a id="__codelineno-10-9" name="__codelineno-10-9" href="#__codelineno-10-9"></a><span class="p">}</span>
</span></code></pre></div>
<p>A instrução break não encerra o loop <code>for</code>: em vez disso, ela encerra a instrução <code>switch</code>. Portanto, em vez de iterar de 0 a 2, este código itera de 0 a 4: <code>0 1 2 3 4</code>.</p>
<p>Uma regra essencial a ter em mente é que uma instrução <code>break</code> encerra a execução da instrução <code>for</code>, <code>switch</code>, ou mais interna <code>select</code>. No exemplo anterior, ele encerra a instrução <code>switch</code>.</p>
<p>Para quebrar o loop em vez da instrução <code>switch</code>, a maneira mais idiomática é usar um rótulo:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-11-1"><a id="__codelineno-11-1" name="__codelineno-11-1" href="#__codelineno-11-1"></a><span class="hll"><span class="nx">loop</span><span class="p">:</span>
</span></span><span id="__span-11-2"><a id="__codelineno-11-2" name="__codelineno-11-2" href="#__codelineno-11-2"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="p">&lt;</span><span class="w"> </span><span class="mi">5</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-11-3"><a id="__codelineno-11-3" name="__codelineno-11-3" href="#__codelineno-11-3"></a><span class="w"> </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%d &quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="p">)</span>
</span><span id="__span-11-4"><a id="__codelineno-11-4" name="__codelineno-11-4" href="#__codelineno-11-4"></a>
</span><span id="__span-11-5"><a id="__codelineno-11-5" name="__codelineno-11-5" href="#__codelineno-11-5"></a><span class="w"> </span><span class="k">switch</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-11-6"><a id="__codelineno-11-6" name="__codelineno-11-6" href="#__codelineno-11-6"></a><span class="w"> </span><span class="k">default</span><span class="p">:</span>
</span><span id="__span-11-7"><a id="__codelineno-11-7" name="__codelineno-11-7" href="#__codelineno-11-7"></a><span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="mi">2</span><span class="p">:</span>
</span><span id="__span-11-8"><a id="__codelineno-11-8" name="__codelineno-11-8" href="#__codelineno-11-8"></a><span class="hll"><span class="w"> </span><span class="k">break</span><span class="w"> </span><span class="nx">loop</span>
</span></span><span id="__span-11-9"><a id="__codelineno-11-9" name="__codelineno-11-9" href="#__codelineno-11-9"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-11-10"><a id="__codelineno-11-10" name="__codelineno-11-10" href="#__codelineno-11-10"></a><span class="w"> </span><span class="p">}</span>
</span></code></pre></div>
<p>Aqui, associamos o <code>loop</code>rótulo ao <code>for</code> loop. Então, como fornecemos o <code>loop</code> rótulo para a instrução <code>break</code>, ela interrompe o loop, não a opção. Portanto, esta nova versão será impressa <code>0 1 2</code>, como esperávamos.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/34-break/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="usando-defer-dentro-de-um-loop-35">Usando <code>defer</code> dentro de um loop (#35)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Extrair a lógica do loop dentro de uma função leva à execução de uma instrução <code>defer</code> no final de cada iteração.</p>
</details>
<p>A instrução <code>defer</code> atrasa a execução de uma chamada até que a função circundante retorne. É usado principalmente para reduzir o código padrão. Por exemplo, se um recurso precisar ser fechado eventualmente, podemos usar <code>defer</code> para evitar a repetição das chamadas de fechamento antes de cada <code>return</code>.</p>
<p>Um erro comum com <code>defer</code> é esquecer que ele agenda uma chamada de função quando a função <em>circundante</em> retorna. Por exemplo:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-12-1"><a id="__codelineno-12-1" name="__codelineno-12-1" href="#__codelineno-12-1"></a><span class="kd">func</span><span class="w"> </span><span class="nx">readFiles</span><span class="p">(</span><span class="nx">ch</span><span class="w"> </span><span class="o">&lt;-</span><span class="kd">chan</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="w"> </span><span class="kt">error</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-12-2"><a id="__codelineno-12-2" name="__codelineno-12-2" href="#__codelineno-12-2"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="nx">path</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">ch</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-12-3"><a id="__codelineno-12-3" name="__codelineno-12-3" href="#__codelineno-12-3"></a><span class="w"> </span><span class="nx">file</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">os</span><span class="p">.</span><span class="nx">Open</span><span class="p">(</span><span class="nx">path</span><span class="p">)</span>
</span><span id="__span-12-4"><a id="__codelineno-12-4" name="__codelineno-12-4" href="#__codelineno-12-4"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-12-5"><a id="__codelineno-12-5" name="__codelineno-12-5" href="#__codelineno-12-5"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">err</span>
</span><span id="__span-12-6"><a id="__codelineno-12-6" name="__codelineno-12-6" href="#__codelineno-12-6"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-12-7"><a id="__codelineno-12-7" name="__codelineno-12-7" href="#__codelineno-12-7"></a>
</span><span id="__span-12-8"><a id="__codelineno-12-8" name="__codelineno-12-8" href="#__codelineno-12-8"></a><span class="w"> </span><span class="k">defer</span><span class="w"> </span><span class="nx">file</span><span class="p">.</span><span class="nx">Close</span><span class="p">()</span>
</span><span id="__span-12-9"><a id="__codelineno-12-9" name="__codelineno-12-9" href="#__codelineno-12-9"></a>
</span><span id="__span-12-10"><a id="__codelineno-12-10" name="__codelineno-12-10" href="#__codelineno-12-10"></a><span class="w"> </span><span class="c1">// Do something with file</span>
</span><span id="__span-12-11"><a id="__codelineno-12-11" name="__codelineno-12-11" href="#__codelineno-12-11"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-12-12"><a id="__codelineno-12-12" name="__codelineno-12-12" href="#__codelineno-12-12"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="kc">nil</span>
</span><span id="__span-12-13"><a id="__codelineno-12-13" name="__codelineno-12-13" href="#__codelineno-12-13"></a><span class="p">}</span>
</span></code></pre></div>
<p>As chamadas <code>defer</code> não são executadas durante cada iteração do loop, mas quando a função <code>readFiles</code> retorna. Se <code>readFiles</code> não retornar, os descritores de arquivos ficarão abertos para sempre, causando vazamentos.</p>
<p>Uma opção comum para corrigir esse problema é criar uma função circundante após <code>defer</code>, chamada durante cada iteração:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-13-1"><a id="__codelineno-13-1" name="__codelineno-13-1" href="#__codelineno-13-1"></a><span class="kd">func</span><span class="w"> </span><span class="nx">readFiles</span><span class="p">(</span><span class="nx">ch</span><span class="w"> </span><span class="o">&lt;-</span><span class="kd">chan</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="w"> </span><span class="kt">error</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-13-2"><a id="__codelineno-13-2" name="__codelineno-13-2" href="#__codelineno-13-2"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="nx">path</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">ch</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-13-3"><a id="__codelineno-13-3" name="__codelineno-13-3" href="#__codelineno-13-3"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">readFile</span><span class="p">(</span><span class="nx">path</span><span class="p">);</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-13-4"><a id="__codelineno-13-4" name="__codelineno-13-4" href="#__codelineno-13-4"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">err</span>
</span><span id="__span-13-5"><a id="__codelineno-13-5" name="__codelineno-13-5" href="#__codelineno-13-5"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-13-6"><a id="__codelineno-13-6" name="__codelineno-13-6" href="#__codelineno-13-6"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-13-7"><a id="__codelineno-13-7" name="__codelineno-13-7" href="#__codelineno-13-7"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="kc">nil</span>
</span><span id="__span-13-8"><a id="__codelineno-13-8" name="__codelineno-13-8" href="#__codelineno-13-8"></a><span class="p">}</span>
</span><span id="__span-13-9"><a id="__codelineno-13-9" name="__codelineno-13-9" href="#__codelineno-13-9"></a>
</span><span id="__span-13-10"><a id="__codelineno-13-10" name="__codelineno-13-10" href="#__codelineno-13-10"></a><span class="kd">func</span><span class="w"> </span><span class="nx">readFile</span><span class="p">(</span><span class="nx">path</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="w"> </span><span class="kt">error</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-13-11"><a id="__codelineno-13-11" name="__codelineno-13-11" href="#__codelineno-13-11"></a><span class="w"> </span><span class="nx">file</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">os</span><span class="p">.</span><span class="nx">Open</span><span class="p">(</span><span class="nx">path</span><span class="p">)</span>
</span><span id="__span-13-12"><a id="__codelineno-13-12" name="__codelineno-13-12" href="#__codelineno-13-12"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-13-13"><a id="__codelineno-13-13" name="__codelineno-13-13" href="#__codelineno-13-13"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">err</span>
</span><span id="__span-13-14"><a id="__codelineno-13-14" name="__codelineno-13-14" href="#__codelineno-13-14"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-13-15"><a id="__codelineno-13-15" name="__codelineno-13-15" href="#__codelineno-13-15"></a>
</span><span id="__span-13-16"><a id="__codelineno-13-16" name="__codelineno-13-16" href="#__codelineno-13-16"></a><span class="w"> </span><span class="k">defer</span><span class="w"> </span><span class="nx">file</span><span class="p">.</span><span class="nx">Close</span><span class="p">()</span>
</span><span id="__span-13-17"><a id="__codelineno-13-17" name="__codelineno-13-17" href="#__codelineno-13-17"></a>
</span><span id="__span-13-18"><a id="__codelineno-13-18" name="__codelineno-13-18" href="#__codelineno-13-18"></a><span class="w"> </span><span class="c1">// Do something with file</span>
</span><span id="__span-13-19"><a id="__codelineno-13-19" name="__codelineno-13-19" href="#__codelineno-13-19"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="kc">nil</span>
</span><span id="__span-13-20"><a id="__codelineno-13-20" name="__codelineno-13-20" href="#__codelineno-13-20"></a><span class="p">}</span>
</span></code></pre></div>
<p>Outra solução é tornar a função <code>readFile</code> um encerramento, mas intrinsecamente, esta permanece a mesma solução: adicionar outra função circundante para executar as chamadas <code>defer</code> durante cada iteração.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/35-defer-loop/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h2 id="strings">Strings</h2>
<h3 id="nao-entendendo-o-conceito-de-rune-36">Não entendendo o conceito de rune (#36)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Entender que uma runa corresponde ao conceito de um ponto de código Unicode e que pode ser composta de múltiplos bytes deve fazer parte do conhecimento básico do desenvolvedor Go para trabalhar com precisão com strings.</p>
</details>
<p>Como as runas estão por toda parte no Go, é importante entender o seguinte:</p>
<ul>
<li>Um conjunto de caracteres é um conjunto de caracteres, enquanto uma codificação descreve como traduzir um conjunto de caracteres em binário.</li>
<li>No Go, uma string faz referência a uma fatia imutável de bytes arbitrários.</li>
<li>O código-fonte Go é codificado usando UTF-8. Portanto, todos os literais de string são strings UTF-8. Mas como uma string pode conter bytes arbitrários, se for obtida de outro lugar (não do código-fonte), não há garantia de que seja baseada na codificação UTF-8.</li>
<li>A <code>rune</code> corresponde ao conceito de ponto de código Unicode, significando um item representado por um único valor.</li>
<li>Usando UTF-8, um ponto de código Unicode pode ser codificado em 1 a 4 bytes.</li>
<li>Usar <code>len()</code> na string em Go retorna o número de bytes, não o número de runas.</li>
</ul>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/36-rune/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="iteracao-de-string-imprecisa-37">Iteração de string imprecisa (#37)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Iterar em uma string com o operador <code>range</code> itera nas runas com o índice correspondente ao índice inicial da sequência de bytes da runa. Para acessar um índice de runa específico (como a terceira runa), converta a string em um arquivo <code>[]rune</code>.</p>
</details>
<p>Iterar em uma string é uma operação comum para desenvolvedores. Talvez queiramos realizar uma operação para cada runa na string ou implementar uma função personalizada para procurar uma substring específica. Em ambos os casos, temos que iterar nas diferentes runas de uma string. Mas é fácil ficar confuso sobre como funciona a iteração.</p>
<p>For example, consider the following example:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-14-1"><a id="__codelineno-14-1" name="__codelineno-14-1" href="#__codelineno-14-1"></a><span class="nx">s</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="s">&quot;hêllo&quot;</span>
</span><span id="__span-14-2"><a id="__codelineno-14-2" name="__codelineno-14-2" href="#__codelineno-14-2"></a><span class="k">for</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">s</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-14-3"><a id="__codelineno-14-3" name="__codelineno-14-3" href="#__codelineno-14-3"></a><span class="w"> </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;position %d: %c\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="p">,</span><span class="w"> </span><span class="nx">s</span><span class="p">[</span><span class="nx">i</span><span class="p">])</span>
</span><span id="__span-14-4"><a id="__codelineno-14-4" name="__codelineno-14-4" href="#__codelineno-14-4"></a><span class="p">}</span>
</span><span id="__span-14-5"><a id="__codelineno-14-5" name="__codelineno-14-5" href="#__codelineno-14-5"></a><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;len=%d\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="nb">len</span><span class="p">(</span><span class="nx">s</span><span class="p">))</span>
</span></code></pre></div>
<div class="language-text highlight"><pre><span></span><code><span id="__span-15-1"><a id="__codelineno-15-1" name="__codelineno-15-1" href="#__codelineno-15-1"></a>position 0: h
</span><span id="__span-15-2"><a id="__codelineno-15-2" name="__codelineno-15-2" href="#__codelineno-15-2"></a>position 1: Ã
</span><span id="__span-15-3"><a id="__codelineno-15-3" name="__codelineno-15-3" href="#__codelineno-15-3"></a>position 3: l
</span><span id="__span-15-4"><a id="__codelineno-15-4" name="__codelineno-15-4" href="#__codelineno-15-4"></a>position 4: l
</span><span id="__span-15-5"><a id="__codelineno-15-5" name="__codelineno-15-5" href="#__codelineno-15-5"></a>position 5: o
</span><span id="__span-15-6"><a id="__codelineno-15-6" name="__codelineno-15-6" href="#__codelineno-15-6"></a>len=6
</span></code></pre></div>
<p>Vamos destacar três pontos que podem ser confusos:</p>
<ul>
<li>A segunda runa é Ã na saída em vez de ê.</li>
<li>Saltamos da posição 1 para a posição 3: o que há na posição 2?</li>
<li>len retorna uma contagem de 6, enquanto s contém apenas 5 runas.</li>
</ul>
<p>Vamos começar com a última observação. Já mencionamos que len retorna o número de bytes em uma string, não o número de runas. Como atribuímos uma string literal a <code>s</code>, <code>s</code> é uma string UTF-8. Enquanto isso, o caractere especial “ê” não é codificado em um único byte; requer 2 bytes. Portanto, chamar <code>len(s)</code> retorna 6.</p>
<p>Enquanto isso, no exemplo anterior, temos que entender que não repetimos cada runa; em vez disso, iteramos sobre cada índice inicial de uma runa:</p>
<p><a class="glightbox" href="../img/rune.png" data-type="image" data-width="auto" data-height="auto" data-desc-position="bottom"><img alt="" src="../img/rune.png" /></a></p>
<p>Imprimir <code>s[i]</code> não imprime a i-ésima runa; imprime a representação UTF-8 do byte em index <code>i</code>. Portanto, imprimimos "hÃllo" em vez de "hêllo".</p>
<p>Se quisermos imprimir todas as diferentes runas, podemos usar o elemento value do operador <code>range</code>:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-16-1"><a id="__codelineno-16-1" name="__codelineno-16-1" href="#__codelineno-16-1"></a><span class="nx">s</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="s">&quot;hêllo&quot;</span>
</span><span id="__span-16-2"><a id="__codelineno-16-2" name="__codelineno-16-2" href="#__codelineno-16-2"></a><span class="k">for</span><span class="w"> </span><span class="nx">i</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">s</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-16-3"><a id="__codelineno-16-3" name="__codelineno-16-3" href="#__codelineno-16-3"></a><span class="w"> </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;position %d: %c\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">)</span>
</span><span id="__span-16-4"><a id="__codelineno-16-4" name="__codelineno-16-4" href="#__codelineno-16-4"></a><span class="p">}</span>
</span></code></pre></div>
<p>Ou podemos converter a string em uma fatia de runas e iterar sobre ela:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-17-1"><a id="__codelineno-17-1" name="__codelineno-17-1" href="#__codelineno-17-1"></a><span class="nx">s</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="s">&quot;hêllo&quot;</span>
</span><span id="__span-17-2"><a id="__codelineno-17-2" name="__codelineno-17-2" href="#__codelineno-17-2"></a><span class="hll"><span class="nx">runes</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="p">[]</span><span class="nb">rune</span><span class="p">(</span><span class="nx">s</span><span class="p">)</span>
</span></span><span id="__span-17-3"><a id="__codelineno-17-3" name="__codelineno-17-3" href="#__codelineno-17-3"></a><span class="k">for</span><span class="w"> </span><span class="nx">i</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">runes</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-17-4"><a id="__codelineno-17-4" name="__codelineno-17-4" href="#__codelineno-17-4"></a><span class="w"> </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;position %d: %c\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">)</span>
</span><span id="__span-17-5"><a id="__codelineno-17-5" name="__codelineno-17-5" href="#__codelineno-17-5"></a><span class="p">}</span>
</span></code></pre></div>
<p>Observe que esta solução introduz uma sobrecarga de tempo de execução em comparação com a anterior. Na verdade, converter uma string em uma fatia de runas requer a alocação de uma fatia adicional e a conversão dos bytes em runas: uma complexidade de tempo O(n) com n o número de bytes na string. Portanto, se quisermos iterar todas as runas, devemos usar a primeira solução.</p>
<p>Porém, se quisermos acessar a i-ésima runa de uma string com a primeira opção, não teremos acesso ao índice da runa; em vez disso, conhecemos o índice inicial de uma runa na sequência de bytes.</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-18-1"><a id="__codelineno-18-1" name="__codelineno-18-1" href="#__codelineno-18-1"></a><span class="nx">s</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="s">&quot;hêllo&quot;</span>
</span><span id="__span-18-2"><a id="__codelineno-18-2" name="__codelineno-18-2" href="#__codelineno-18-2"></a><span class="nx">r</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="p">[]</span><span class="nb">rune</span><span class="p">(</span><span class="nx">s</span><span class="p">)[</span><span class="mi">4</span><span class="p">]</span>
</span><span id="__span-18-3"><a id="__codelineno-18-3" name="__codelineno-18-3" href="#__codelineno-18-3"></a><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%c\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">)</span><span class="w"> </span><span class="c1">// o</span>
</span></code></pre></div>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/37-string-iteration/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="uso-indevido-de-funcoes-de-trim-38">Uso indevido de funções de trim (#38)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p><code>strings.TrimRight</code>/<code>strings.TrimLeft</code> remove todas as runas finais/iniciais contidas em um determinado conjunto, enquanto <code>strings.TrimSuffix</code>/<code>strings.TrimPrefix</code> retorna uma string sem um sufixo/prefixo fornecido.</p>
</details>
<p>Por exemplo:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-19-1"><a id="__codelineno-19-1" name="__codelineno-19-1" href="#__codelineno-19-1"></a><span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="nx">strings</span><span class="p">.</span><span class="nx">TrimRight</span><span class="p">(</span><span class="s">&quot;123oxo&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;xo&quot;</span><span class="p">))</span>
</span></code></pre></div>
<p>O exemplo imprime 123:</p>
<p><a class="glightbox" href="../img/trim.png" data-type="image" data-width="auto" data-height="auto" data-desc-position="bottom"><img alt="" src="../img/trim.png" /></a></p>
<p>Por outro lado, <code>strings.TrimLeft</code> remove todas as runas principais contidas em um conjunto.</p>
<p>Por outro lado, <code>strings.TrimSuffix</code>/<code>strings.TrimPrefix</code> retorna uma string sem o sufixo/prefixo final fornecido.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/38-trim/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="concatenacao-de-strings-subotimizada-39">Concatenação de strings subotimizada (#39)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>A concatenação de uma lista de strings deve ser feita com <code>strings.Builder</code> para evitar a alocação de uma nova string durante cada iteração.</p>
</details>
<p>Vamos considerar uma função <code>concat</code> que concatena todos os elementos string de uma fatia usando o operador <code>+=</code>:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-20-1"><a id="__codelineno-20-1" name="__codelineno-20-1" href="#__codelineno-20-1"></a><span class="kd">func</span><span class="w"> </span><span class="nx">concat</span><span class="p">(</span><span class="nx">values</span><span class="w"> </span><span class="p">[]</span><span class="kt">string</span><span class="p">)</span><span class="w"> </span><span class="kt">string</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-20-2"><a id="__codelineno-20-2" name="__codelineno-20-2" href="#__codelineno-20-2"></a><span class="w"> </span><span class="nx">s</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="s">&quot;&quot;</span>
</span><span id="__span-20-3"><a id="__codelineno-20-3" name="__codelineno-20-3" href="#__codelineno-20-3"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">value</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">values</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-20-4"><a id="__codelineno-20-4" name="__codelineno-20-4" href="#__codelineno-20-4"></a><span class="w"> </span><span class="nx">s</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="nx">value</span>
</span><span id="__span-20-5"><a id="__codelineno-20-5" name="__codelineno-20-5" href="#__codelineno-20-5"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-20-6"><a id="__codelineno-20-6" name="__codelineno-20-6" href="#__codelineno-20-6"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">s</span>
</span><span id="__span-20-7"><a id="__codelineno-20-7" name="__codelineno-20-7" href="#__codelineno-20-7"></a><span class="p">}</span>
</span></code></pre></div>
<p>Durante cada iteração, o operador <code>+=</code> concatena com <code>s</code> a sequência de valores. À primeira vista, esta função pode não parecer errada. Mas com esta implementação, esquecemos uma das principais características de uma string: a sua imutabilidade. Portanto, cada iteração não é atualizada <code>s</code>; ele realoca uma nova string na memória, o que impacta significativamente o desempenho desta função.</p>
<p>Felizmente, existe uma solução para lidar com esse problema, usando <code>strings.Builder</code>:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-21-1"><a id="__codelineno-21-1" name="__codelineno-21-1" href="#__codelineno-21-1"></a><span class="kd">func</span><span class="w"> </span><span class="nx">concat</span><span class="p">(</span><span class="nx">values</span><span class="w"> </span><span class="p">[]</span><span class="kt">string</span><span class="p">)</span><span class="w"> </span><span class="kt">string</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-21-2"><a id="__codelineno-21-2" name="__codelineno-21-2" href="#__codelineno-21-2"></a><span class="hll"><span class="w"> </span><span class="nx">sb</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">strings</span><span class="p">.</span><span class="nx">Builder</span><span class="p">{}</span>
</span></span><span id="__span-21-3"><a id="__codelineno-21-3" name="__codelineno-21-3" href="#__codelineno-21-3"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">value</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">values</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-21-4"><a id="__codelineno-21-4" name="__codelineno-21-4" href="#__codelineno-21-4"></a><span class="hll"><span class="w"> </span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">_</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">sb</span><span class="p">.</span><span class="nx">WriteString</span><span class="p">(</span><span class="nx">value</span><span class="p">)</span>
</span></span><span id="__span-21-5"><a id="__codelineno-21-5" name="__codelineno-21-5" href="#__codelineno-21-5"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-21-6"><a id="__codelineno-21-6" name="__codelineno-21-6" href="#__codelineno-21-6"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">sb</span><span class="p">.</span><span class="nx">String</span><span class="p">()</span>
</span><span id="__span-21-7"><a id="__codelineno-21-7" name="__codelineno-21-7" href="#__codelineno-21-7"></a><span class="p">}</span>
</span></code></pre></div>
<p>Durante cada iteração, construímos a string resultante chamando o método <code>WriteString</code> que anexa o conteúdo do valor ao seu buffer interno, minimizando assim a cópia da memória.</p>
<details class="note" open="open">
<summary>Note</summary>
<p><code>WriteString</code> retorna um erro como segunda saída, mas nós o ignoramos propositalmente. Na verdade, este método nunca retornará um erro diferente de zero. Então, qual é o propósito deste método retornar um erro como parte de sua assinatura? <code>strings.Builder</code> implementa a <code>io.StringWriter</code> interface, que contém um único método: <code>WriteString(s string) (n int, err error)</code>. Portanto, para estar em conformidade com esta interface, <code>WriteString</code> deve retornar um erro.</p>
</details>
<p>Internamente, <code>strings.Builder</code> contém uma fatia de bytes. Cada chamada para <code>WriteString</code> resulta em uma chamada para anexar nesta fatia. Existem dois impactos. Primeiro, esta estrutura não deve ser usada simultaneamente, pois as chamadas <code>append</code> levariam a condições de corrida. O segundo impacto é algo que vimos no <a href="#inefficient-slice-initialization-21">mistake #21, "Inicialização de slice ineficiente"</a>: se o comprimento futuro de uma slice já for conhecido, devemos pré-alocá-la. Para isso, <code>strings.Builder</code> expõe um método <code>Grow(n int)</code> para garantir espaço para outros <code>n</code> bytes:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-22-1"><a id="__codelineno-22-1" name="__codelineno-22-1" href="#__codelineno-22-1"></a><span class="kd">func</span><span class="w"> </span><span class="nx">concat</span><span class="p">(</span><span class="nx">values</span><span class="w"> </span><span class="p">[]</span><span class="kt">string</span><span class="p">)</span><span class="w"> </span><span class="kt">string</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-22-2"><a id="__codelineno-22-2" name="__codelineno-22-2" href="#__codelineno-22-2"></a><span class="w"> </span><span class="nx">total</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="mi">0</span>
</span><span id="__span-22-3"><a id="__codelineno-22-3" name="__codelineno-22-3" href="#__codelineno-22-3"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="p">&lt;</span><span class="w"> </span><span class="nb">len</span><span class="p">(</span><span class="nx">values</span><span class="p">);</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-22-4"><a id="__codelineno-22-4" name="__codelineno-22-4" href="#__codelineno-22-4"></a><span class="w"> </span><span class="nx">total</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="nb">len</span><span class="p">(</span><span class="nx">values</span><span class="p">[</span><span class="nx">i</span><span class="p">])</span>
</span><span id="__span-22-5"><a id="__codelineno-22-5" name="__codelineno-22-5" href="#__codelineno-22-5"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-22-6"><a id="__codelineno-22-6" name="__codelineno-22-6" href="#__codelineno-22-6"></a>
</span><span id="__span-22-7"><a id="__codelineno-22-7" name="__codelineno-22-7" href="#__codelineno-22-7"></a><span class="w"> </span><span class="nx">sb</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">strings</span><span class="p">.</span><span class="nx">Builder</span><span class="p">{}</span>
</span><span id="__span-22-8"><a id="__codelineno-22-8" name="__codelineno-22-8" href="#__codelineno-22-8"></a><span class="w"> </span><span class="nx">sb</span><span class="p">.</span><span class="nx">Grow</span><span class="p">(</span><span class="nx">total</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
</span><span id="__span-22-9"><a id="__codelineno-22-9" name="__codelineno-22-9" href="#__codelineno-22-9"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">value</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">values</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-22-10"><a id="__codelineno-22-10" name="__codelineno-22-10" href="#__codelineno-22-10"></a><span class="w"> </span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">_</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">sb</span><span class="p">.</span><span class="nx">WriteString</span><span class="p">(</span><span class="nx">value</span><span class="p">)</span>
</span><span id="__span-22-11"><a id="__codelineno-22-11" name="__codelineno-22-11" href="#__codelineno-22-11"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-22-12"><a id="__codelineno-22-12" name="__codelineno-22-12" href="#__codelineno-22-12"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">sb</span><span class="p">.</span><span class="nx">String</span><span class="p">()</span>
</span><span id="__span-22-13"><a id="__codelineno-22-13" name="__codelineno-22-13" href="#__codelineno-22-13"></a><span class="p">}</span>
</span></code></pre></div>
<p>Vamos executar um benchmark para comparar as três versões (v1 usando <code>+=</code>; v2 usando <code>strings.Builder{}</code> sem pré-alocação; e v3 usando <code>strings.Builder{}</code> com pré-alocação). A slice de entrada contém 1.000 strings e cada string contém 1.000 bytes:</p>
<div class="language-text highlight"><pre><span></span><code><span id="__span-23-1"><a id="__codelineno-23-1" name="__codelineno-23-1" href="#__codelineno-23-1"></a>BenchmarkConcatV1-4 16 72291485 ns/op
</span><span id="__span-23-2"><a id="__codelineno-23-2" name="__codelineno-23-2" href="#__codelineno-23-2"></a>BenchmarkConcatV2-4 1188 878962 ns/op
</span><span id="__span-23-3"><a id="__codelineno-23-3" name="__codelineno-23-3" href="#__codelineno-23-3"></a>BenchmarkConcatV3-4 5922 190340 ns/op
</span></code></pre></div>
<p>Como podemos ver, a versão mais recente é de longe a mais eficiente: 99% mais rápida que a v1 e 78% mais rápida que a v2.</p>
<p><code>strings.Builder</code> é a solução recomendada para concatenar uma lista de strings. Normalmente, esta solução deve ser usada dentro de um loop. Na verdade, se precisarmos apenas concatenar algumas strings (como um nome e um sobrenome), o uso <code>strings.Builder</code> não é recomendado, pois isso tornará o código um pouco menos legível do que usar o operador <code>+=</code> or <code>fmt.Sprintf</code>.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/39-string-concat/"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="conversoes-de-string-inuteis-40">Conversões de string inúteis (#40)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Lembrar que o pacote <code>bytes</code> oferece as mesmas operações que o pacote <code>strings</code> pode ajudar a evitar conversões extras de bytes/string.</p>
</details>
<p>Ao optar por trabalhar com uma string ou um <code>[]byte</code>, a maioria dos programadores tende a preferir strings por conveniência. Mas a maior parte da E/S é realmente feita com <code>[]byte</code>. Por exemplo, <code>io.Reader</code>, <code>io.Writer</code> e <code>io.ReadAll</code> trabalham com <code>[]byte</code>, não com strings.</p>
<p>Quando nos perguntamos se devemos trabalhar com strings ou <code>[]byte</code>, lembremos que trabalhar com <code>[]byte</code>não é necessariamente menos conveniente. Na verdade, todas as funções exportadas do pacote strings também possuem alternativas no pacote <code>bytes</code>: <code>Split</code>, <code>Count</code>, <code>Contains</code>, <code>Index</code> e assim por diante. Portanto, estejamos fazendo I/O ou não, devemos primeiro verificar se poderíamos implementar um fluxo de trabalho completo usando bytes em vez de strings e evitar o preço de conversões adicionais.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/40-string-conversion/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="vazamentos-de-substring-e-memoria-41">Vazamentos de substring e memória (#41)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Usar cópias em vez de substrings pode evitar vazamentos de memória, pois a string retornada por uma operação de substring será apoiada pela mesma matriz de bytes.</p>
</details>
<p>In mistake <a href="#slice-and-memory-leaks--26-">#26, “Slices and memory leaks,”</a> we saw how slicing a slice or array may lead to memory leak situations. This principle also applies to string and substring operations.</p>
<p>We need to keep two things in mind while using the substring operation in Go. First, the interval provided is based on the number of bytes, not the number of runes. Second, a substring operation may lead to a memory leak as the resulting substring will share the same backing array as the initial string. The solutions to prevent this case from happening are to perform a string copy manually or to use <code>strings.Clone</code> from Go 1.18.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/41-substring-memory-leak/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h2 id="functions-and-methods">Functions and Methods</h2>
<h3 id="nao-saber-que-tipo-de-receptor-usar-42">Não saber que tipo de receptor usar (#42)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>A decisão de usar um valor ou um receptor de ponteiro deve ser tomada com base em fatores como o tipo, se deve sofrer mutação, se contém um campo que não pode ser copiado e o tamanho do objeto. Em caso de dúvida, use um receptor de ponteiro.</p>
</details>
<p>Choosing between value and pointer receivers isnt always straightforward. Lets discuss some of the conditions to help us choose.</p>
<p>A receiver <em>must</em> be a pointer</p>
<ul>
<li>If the method needs to mutate the receiver. This rule is also valid if the receiver is a slice and a method needs to append elements:</li>
</ul>
<div class="language-go highlight"><pre><span></span><code><span id="__span-24-1"><a id="__codelineno-24-1" name="__codelineno-24-1" href="#__codelineno-24-1"></a><span class="kd">type</span><span class="w"> </span><span class="nx">slice</span><span class="w"> </span><span class="p">[]</span><span class="kt">int</span>
</span><span id="__span-24-2"><a id="__codelineno-24-2" name="__codelineno-24-2" href="#__codelineno-24-2"></a>
</span><span id="__span-24-3"><a id="__codelineno-24-3" name="__codelineno-24-3" href="#__codelineno-24-3"></a><span class="kd">func</span><span class="w"> </span><span class="p">(</span><span class="nx">s</span><span class="w"> </span><span class="o">*</span><span class="nx">slice</span><span class="p">)</span><span class="w"> </span><span class="nx">add</span><span class="p">(</span><span class="nx">element</span><span class="w"> </span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-24-4"><a id="__codelineno-24-4" name="__codelineno-24-4" href="#__codelineno-24-4"></a><span class="w"> </span><span class="o">*</span><span class="nx">s</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nb">append</span><span class="p">(</span><span class="o">*</span><span class="nx">s</span><span class="p">,</span><span class="w"> </span><span class="nx">element</span><span class="p">)</span>
</span><span id="__span-24-5"><a id="__codelineno-24-5" name="__codelineno-24-5" href="#__codelineno-24-5"></a><span class="p">}</span>
</span></code></pre></div>
<ul>
<li>If the method receiver contains a field that cannot be copied: for example, a type part of the sync package (see <a href="#copying-a-sync-type--74-">#74, “Copying a sync type”</a>).</li>
</ul>
<p>A receiver <em>should</em> be a pointer</p>
<ul>
<li>If the receiver is a large object. Using a pointer can make the call more efficient, as doing so prevents making an extensive copy. When in doubt about how large is large, benchmarking can be the solution; its pretty much impossible to state a specific size, because it depends on many factors.</li>
</ul>
<p>A receiver <em>must</em> be a value</p>
<ul>
<li>If we have to enforce a receivers immutability.</li>
<li>If the receiver is a map, function, or channel. Otherwise, a compilation error
occurs.</li>
</ul>
<p>A receiver <em>should</em> be a value</p>
<ul>
<li>If the receiver is a slice that doesnt have to be mutated.</li>
<li>If the receiver is a small array or struct that is naturally a value type without mutable fields, such as <code>time.Time</code>.</li>
<li>If the receiver is a basic type such as <code>int</code>, <code>float64</code>, or <code>string</code>.</li>
</ul>
<p>Of course, its impossible to be exhaustive, as there will always be edge cases, but this sections goal was to provide guidance to cover most cases. By default, we can choose to go with a value receiver unless theres a good reason not to do so. In doubt, we should use a pointer receiver.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/42-receiver/"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="nunca-usando-parametros-de-resultado-nomeados-43">Nunca usando parâmetros de resultado nomeados (#43)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Usar parâmetros de resultado nomeados pode ser uma maneira eficiente de melhorar a legibilidade de uma função/método, especialmente se vários parâmetros de resultado tiverem o mesmo tipo. Em alguns casos, esta abordagem também pode ser conveniente porque os parâmetros de resultado nomeados são inicializados com seu valor zero. Mas tenha cuidado com os possíveis efeitos colaterais.</p>
</details>
<p>When we return parameters in a function or a method, we can attach names to these parameters and use them as regular variables. When a result parameter is named, its initialized to its zero value when the function/method begins. With named result parameters, we can also call a naked return statement (without arguments). In that case, the current values of the result parameters are used as the returned values.</p>
<p>Heres an example that uses a named result parameter <code>b</code>:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-25-1"><a id="__codelineno-25-1" name="__codelineno-25-1" href="#__codelineno-25-1"></a><span class="kd">func</span><span class="w"> </span><span class="nx">f</span><span class="p">(</span><span class="nx">a</span><span class="w"> </span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="nx">b</span><span class="w"> </span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-25-2"><a id="__codelineno-25-2" name="__codelineno-25-2" href="#__codelineno-25-2"></a><span class="w"> </span><span class="nx">b</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">a</span>
</span><span id="__span-25-3"><a id="__codelineno-25-3" name="__codelineno-25-3" href="#__codelineno-25-3"></a><span class="w"> </span><span class="k">return</span>
</span><span id="__span-25-4"><a id="__codelineno-25-4" name="__codelineno-25-4" href="#__codelineno-25-4"></a><span class="p">}</span>
</span></code></pre></div>
<p>In this example, we attach a name to the result parameter: <code>b</code>. When we call return without arguments, it returns the current value of <code>b</code>.</p>
<p>In some cases, named result parameters can also increase readability: for example, if two parameters have the same type. In other cases, they can also be used for convenience. Therefore, we should use named result parameters sparingly when theres a clear benefit.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/43-named-result-parameters/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="efeitos-colaterais-nao-intencionais-com-parametros-de-resultado-nomeados-44">Efeitos colaterais não intencionais com parâmetros de resultado nomeados (#44)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Consulte <a href="#never-using-named-result-parameters-43">#43</a>.</p>
</details>
<p>We mentioned why named result parameters can be useful in some situations. But as these result parameters are initialized to their zero value, using them can sometimes lead to subtle bugs if were not careful enough. For example, can you spot whats wrong with this code?</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-26-1"><a id="__codelineno-26-1" name="__codelineno-26-1" href="#__codelineno-26-1"></a><span class="kd">func</span><span class="w"> </span><span class="p">(</span><span class="nx">l</span><span class="w"> </span><span class="nx">loc</span><span class="p">)</span><span class="w"> </span><span class="nx">getCoordinates</span><span class="p">(</span><span class="nx">ctx</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">Context</span><span class="p">,</span><span class="w"> </span><span class="nx">address</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="w"> </span><span class="p">(</span>
</span><span id="__span-26-2"><a id="__codelineno-26-2" name="__codelineno-26-2" href="#__codelineno-26-2"></a><span class="w"> </span><span class="nx">lat</span><span class="p">,</span><span class="w"> </span><span class="nx">lng</span><span class="w"> </span><span class="kt">float32</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="kt">error</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-26-3"><a id="__codelineno-26-3" name="__codelineno-26-3" href="#__codelineno-26-3"></a><span class="w"> </span><span class="nx">isValid</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">l</span><span class="p">.</span><span class="nx">validateAddress</span><span class="p">(</span><span class="nx">address</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
</span><span id="__span-26-4"><a id="__codelineno-26-4" name="__codelineno-26-4" href="#__codelineno-26-4"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">!</span><span class="nx">isValid</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-26-5"><a id="__codelineno-26-5" name="__codelineno-26-5" href="#__codelineno-26-5"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="nx">errors</span><span class="p">.</span><span class="nx">New</span><span class="p">(</span><span class="s">&quot;invalid address&quot;</span><span class="p">)</span>
</span><span id="__span-26-6"><a id="__codelineno-26-6" name="__codelineno-26-6" href="#__codelineno-26-6"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-26-7"><a id="__codelineno-26-7" name="__codelineno-26-7" href="#__codelineno-26-7"></a>
</span><span id="__span-26-8"><a id="__codelineno-26-8" name="__codelineno-26-8" href="#__codelineno-26-8"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">ctx</span><span class="p">.</span><span class="nx">Err</span><span class="p">()</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
</span><span id="__span-26-9"><a id="__codelineno-26-9" name="__codelineno-26-9" href="#__codelineno-26-9"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span>
</span><span id="__span-26-10"><a id="__codelineno-26-10" name="__codelineno-26-10" href="#__codelineno-26-10"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-26-11"><a id="__codelineno-26-11" name="__codelineno-26-11" href="#__codelineno-26-11"></a>
</span><span id="__span-26-12"><a id="__codelineno-26-12" name="__codelineno-26-12" href="#__codelineno-26-12"></a><span class="w"> </span><span class="c1">// Get and return coordinates</span>
</span><span id="__span-26-13"><a id="__codelineno-26-13" name="__codelineno-26-13" href="#__codelineno-26-13"></a><span class="p">}</span>
</span></code></pre></div>
<p>The error might not be obvious at first glance. Here, the error returned in the <code>if ctx.Err() != nil</code> scope is <code>err</code>. But we havent assigned any value to the <code>err</code> variable. Its still assigned to the zero value of an <code>error</code> type: <code>nil</code>. Hence, this code will always return a nil error.</p>
<p>When using named result parameters, we must recall that each parameter is initialized to its zero value. As we have seen in this section, this can lead to subtle bugs that arent always straightforward to spot while reading code. Therefore, lets remain cautious when using named result parameters, to avoid potential side effects.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/44-side-effects-named-result-parameters/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="retornando-um-receptor-nulo-45">Retornando um receptor nulo (#45)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Ao retornar uma interface, tenha cuidado para não retornar um ponteiro nulo, mas um valor nulo explícito. Caso contrário, poderão ocorrer consequências não intencionais e o chamador receberá um valor diferente de zero.</p>
</details>
<!-- TODO -->
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/45-nil-receiver/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="usando-um-nome-de-arquivo-como-entrada-de-funcao-46">Usando um nome de arquivo como entrada de função (#46)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Projetar funções para receber tipos <code>io.Reader</code> em vez de nomes de arquivos melhora a capacidade de reutilização de uma função e facilita o teste.</p>
</details>
<p>Accepting a filename as a function input to read from a file should, in most cases, be considered a code smell (except in specific functions such as <code>os.Open</code>). Indeed, it makes unit tests more complex because we may have to create multiple files. It also reduces the reusability of a function (although not all functions are meant to be reused). Using the <code>io.Reader</code> interface abstracts the data source. Regardless of whether the input is a file, a string, an HTTP request, or a gRPC request, the implementation can be reused and easily tested.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/46-function-input/"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="ignorando-como-argumentos-defer-e-receptores-sao-avaliados-avaliacao-de-argumentos-ponteiros-e-receptores-de-valor-47">Ignorando como argumentos <code>defer</code> e receptores são avaliados (avaliação de argumentos, ponteiros e receptores de valor) (#47)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Passar um ponteiro para uma função <code>defer</code> e agrupar uma chamada dentro de um closure são duas soluções possíveis para superar a avaliação imediata de argumentos e receptores.</p>
</details>
<p>In a <code>defer</code> function the arguments are evaluated right away, not once the surrounding function returns. For example, in this code, we always call <code>notify</code> and <code>incrementCounter</code> with the same status: an empty string.</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-27-1"><a id="__codelineno-27-1" name="__codelineno-27-1" href="#__codelineno-27-1"></a><span class="kd">const</span><span class="w"> </span><span class="p">(</span>
</span><span id="__span-27-2"><a id="__codelineno-27-2" name="__codelineno-27-2" href="#__codelineno-27-2"></a><span class="w"> </span><span class="nx">StatusSuccess</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s">&quot;success&quot;</span>
</span><span id="__span-27-3"><a id="__codelineno-27-3" name="__codelineno-27-3" href="#__codelineno-27-3"></a><span class="w"> </span><span class="nx">StatusErrorFoo</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s">&quot;error_foo&quot;</span>
</span><span id="__span-27-4"><a id="__codelineno-27-4" name="__codelineno-27-4" href="#__codelineno-27-4"></a><span class="w"> </span><span class="nx">StatusErrorBar</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s">&quot;error_bar&quot;</span>
</span><span id="__span-27-5"><a id="__codelineno-27-5" name="__codelineno-27-5" href="#__codelineno-27-5"></a><span class="p">)</span>
</span><span id="__span-27-6"><a id="__codelineno-27-6" name="__codelineno-27-6" href="#__codelineno-27-6"></a>
</span><span id="__span-27-7"><a id="__codelineno-27-7" name="__codelineno-27-7" href="#__codelineno-27-7"></a><span class="kd">func</span><span class="w"> </span><span class="nx">f</span><span class="p">()</span><span class="w"> </span><span class="kt">error</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-27-8"><a id="__codelineno-27-8" name="__codelineno-27-8" href="#__codelineno-27-8"></a><span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">status</span><span class="w"> </span><span class="kt">string</span>
</span><span id="__span-27-9"><a id="__codelineno-27-9" name="__codelineno-27-9" href="#__codelineno-27-9"></a><span class="w"> </span><span class="k">defer</span><span class="w"> </span><span class="nx">notify</span><span class="p">(</span><span class="nx">status</span><span class="p">)</span>
</span><span id="__span-27-10"><a id="__codelineno-27-10" name="__codelineno-27-10" href="#__codelineno-27-10"></a><span class="w"> </span><span class="k">defer</span><span class="w"> </span><span class="nx">incrementCounter</span><span class="p">(</span><span class="nx">status</span><span class="p">)</span>
</span><span id="__span-27-11"><a id="__codelineno-27-11" name="__codelineno-27-11" href="#__codelineno-27-11"></a>
</span><span id="__span-27-12"><a id="__codelineno-27-12" name="__codelineno-27-12" href="#__codelineno-27-12"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">foo</span><span class="p">();</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-27-13"><a id="__codelineno-27-13" name="__codelineno-27-13" href="#__codelineno-27-13"></a><span class="w"> </span><span class="nx">status</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">StatusErrorFoo</span>
</span><span id="__span-27-14"><a id="__codelineno-27-14" name="__codelineno-27-14" href="#__codelineno-27-14"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">err</span>
</span><span id="__span-27-15"><a id="__codelineno-27-15" name="__codelineno-27-15" href="#__codelineno-27-15"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-27-16"><a id="__codelineno-27-16" name="__codelineno-27-16" href="#__codelineno-27-16"></a>
</span><span id="__span-27-17"><a id="__codelineno-27-17" name="__codelineno-27-17" href="#__codelineno-27-17"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">bar</span><span class="p">();</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-27-18"><a id="__codelineno-27-18" name="__codelineno-27-18" href="#__codelineno-27-18"></a><span class="w"> </span><span class="nx">status</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">StatusErrorBar</span>
</span><span id="__span-27-19"><a id="__codelineno-27-19" name="__codelineno-27-19" href="#__codelineno-27-19"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">err</span>
</span><span id="__span-27-20"><a id="__codelineno-27-20" name="__codelineno-27-20" href="#__codelineno-27-20"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-27-21"><a id="__codelineno-27-21" name="__codelineno-27-21" href="#__codelineno-27-21"></a>
</span><span id="__span-27-22"><a id="__codelineno-27-22" name="__codelineno-27-22" href="#__codelineno-27-22"></a><span class="w"> </span><span class="nx">status</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">StatusSuccess</span><span class="w"> </span><span class="p">&lt;</span><span class="mi">5</span><span class="p">&gt;</span>
</span><span id="__span-27-23"><a id="__codelineno-27-23" name="__codelineno-27-23" href="#__codelineno-27-23"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="kc">nil</span>
</span><span id="__span-27-24"><a id="__codelineno-27-24" name="__codelineno-27-24" href="#__codelineno-27-24"></a><span class="p">}</span>
</span></code></pre></div>
<p>Indeed, we call <code>notify(status)</code> and <code>incrementCounter(status)</code> as <code>defer</code> functions. Therefore, Go will delay these calls to be executed once <code>f</code> returns with the current value of status at the stage we used defer, hence passing an empty string.</p>
<p>Two leading options if we want to keep using <code>defer</code>.</p>
<p>The first solution is to pass a string pointer:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-28-1"><a id="__codelineno-28-1" name="__codelineno-28-1" href="#__codelineno-28-1"></a><span class="kd">func</span><span class="w"> </span><span class="nx">f</span><span class="p">()</span><span class="w"> </span><span class="kt">error</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-28-2"><a id="__codelineno-28-2" name="__codelineno-28-2" href="#__codelineno-28-2"></a><span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">status</span><span class="w"> </span><span class="kt">string</span>
</span><span id="__span-28-3"><a id="__codelineno-28-3" name="__codelineno-28-3" href="#__codelineno-28-3"></a><span class="hll"><span class="w"> </span><span class="k">defer</span><span class="w"> </span><span class="nx">notify</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">status</span><span class="p">)</span><span class="w"> </span>
</span></span><span id="__span-28-4"><a id="__codelineno-28-4" name="__codelineno-28-4" href="#__codelineno-28-4"></a><span class="hll"><span class="w"> </span><span class="k">defer</span><span class="w"> </span><span class="nx">incrementCounter</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">status</span><span class="p">)</span>
</span></span><span id="__span-28-5"><a id="__codelineno-28-5" name="__codelineno-28-5" href="#__codelineno-28-5"></a>
</span><span id="__span-28-6"><a id="__codelineno-28-6" name="__codelineno-28-6" href="#__codelineno-28-6"></a><span class="w"> </span><span class="c1">// The rest of the function unchanged</span>
</span><span id="__span-28-7"><a id="__codelineno-28-7" name="__codelineno-28-7" href="#__codelineno-28-7"></a><span class="p">}</span>
</span></code></pre></div>
<p>Using <code>defer</code> evaluates the arguments right away: here, the address of status. Yes, status itself is modified throughout the function, but its address remains constant, regardless of the assignments. Hence, if <code>notify</code> or <code>incrementCounter</code> uses the value referenced by the string pointer, it will work as expected. But this solution requires changing the signature of the two functions, which may not always be possible.</p>
<p>Theres another solution: calling a closure (an anonymous function value that references variables from outside its body) as a <code>defer</code> statement:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-29-1"><a id="__codelineno-29-1" name="__codelineno-29-1" href="#__codelineno-29-1"></a><span class="kd">func</span><span class="w"> </span><span class="nx">f</span><span class="p">()</span><span class="w"> </span><span class="kt">error</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-29-2"><a id="__codelineno-29-2" name="__codelineno-29-2" href="#__codelineno-29-2"></a><span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">status</span><span class="w"> </span><span class="kt">string</span>
</span><span id="__span-29-3"><a id="__codelineno-29-3" name="__codelineno-29-3" href="#__codelineno-29-3"></a><span class="hll"><span class="w"> </span><span class="k">defer</span><span class="w"> </span><span class="kd">func</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
</span></span><span id="__span-29-4"><a id="__codelineno-29-4" name="__codelineno-29-4" href="#__codelineno-29-4"></a><span class="hll"><span class="w"> </span><span class="nx">notify</span><span class="p">(</span><span class="nx">status</span><span class="p">)</span>
</span></span><span id="__span-29-5"><a id="__codelineno-29-5" name="__codelineno-29-5" href="#__codelineno-29-5"></a><span class="hll"><span class="w"> </span><span class="nx">incrementCounter</span><span class="p">(</span><span class="nx">status</span><span class="p">)</span>
</span></span><span id="__span-29-6"><a id="__codelineno-29-6" name="__codelineno-29-6" href="#__codelineno-29-6"></a><span class="hll"><span class="w"> </span><span class="p">}()</span>
</span></span><span id="__span-29-7"><a id="__codelineno-29-7" name="__codelineno-29-7" href="#__codelineno-29-7"></a>
</span><span id="__span-29-8"><a id="__codelineno-29-8" name="__codelineno-29-8" href="#__codelineno-29-8"></a><span class="w"> </span><span class="c1">// The rest of the function unchanged</span>
</span><span id="__span-29-9"><a id="__codelineno-29-9" name="__codelineno-29-9" href="#__codelineno-29-9"></a><span class="p">}</span>
</span></code></pre></div>
<p>Here, we wrap the calls to both <code>notify</code> and <code>incrementCounter</code> within a closure. This closure references the status variable from outside its body. Therefore, <code>status</code> is evaluated once the closure is executed, not when we call <code>defer</code>. This solution also works and doesnt require <code>notify</code> and <code>incrementCounter</code> to change their signature.</p>
<p>Let's also note this behavior applies with method receiver: the receiver is evaluated immediately.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/47-defer-evaluation/"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h2 id="error-management">Error Management</h2>
<h3 id="panico-48">Pânico (#48)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Usar <code>panic</code> é uma opção para lidar com erros no Go. No entanto, só deve ser usado com moderação em condições irrecuperáveis: por exemplo, para sinalizar um erro do programador ou quando você não consegue carregar uma dependência obrigatória.</p>
</details>
<p>In Go, panic is a built-in function that stops the ordinary flow:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-30-1"><a id="__codelineno-30-1" name="__codelineno-30-1" href="#__codelineno-30-1"></a><span class="kd">func</span><span class="w"> </span><span class="nx">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-30-2"><a id="__codelineno-30-2" name="__codelineno-30-2" href="#__codelineno-30-2"></a><span class="w"> </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="s">&quot;a&quot;</span><span class="p">)</span>
</span><span id="__span-30-3"><a id="__codelineno-30-3" name="__codelineno-30-3" href="#__codelineno-30-3"></a><span class="w"> </span><span class="nb">panic</span><span class="p">(</span><span class="s">&quot;foo&quot;</span><span class="p">)</span>
</span><span id="__span-30-4"><a id="__codelineno-30-4" name="__codelineno-30-4" href="#__codelineno-30-4"></a><span class="w"> </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="s">&quot;b&quot;</span><span class="p">)</span>
</span><span id="__span-30-5"><a id="__codelineno-30-5" name="__codelineno-30-5" href="#__codelineno-30-5"></a><span class="p">}</span>
</span></code></pre></div>
<p>This code prints a and then stops before printing b:</p>
<div class="language-text highlight"><pre><span></span><code><span id="__span-31-1"><a id="__codelineno-31-1" name="__codelineno-31-1" href="#__codelineno-31-1"></a>a
</span><span id="__span-31-2"><a id="__codelineno-31-2" name="__codelineno-31-2" href="#__codelineno-31-2"></a>panic: foo
</span><span id="__span-31-3"><a id="__codelineno-31-3" name="__codelineno-31-3" href="#__codelineno-31-3"></a>
</span><span id="__span-31-4"><a id="__codelineno-31-4" name="__codelineno-31-4" href="#__codelineno-31-4"></a>goroutine 1 [running]:
</span><span id="__span-31-5"><a id="__codelineno-31-5" name="__codelineno-31-5" href="#__codelineno-31-5"></a>main.main()
</span><span id="__span-31-6"><a id="__codelineno-31-6" name="__codelineno-31-6" href="#__codelineno-31-6"></a> main.go:7 +0xb3
</span></code></pre></div>
<p>Panicking in Go should be used sparingly. There are two prominent cases, one to signal a programmer error (e.g., <a href="https://cs.opensource.google/go/go/+/refs/tags/go1.20.7:src/database/sql/sql.go;l=44"><code>sql.Register</code></a> that panics if the driver is <code>nil</code> or has already been register) and another where our application fails to create a mandatory dependency. Hence, exceptional conditions that lead us to stop the application. In most other cases, error management should be done with a function that returns a proper error type as the last return argument.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/48-panic/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="ignorando-quando-embrulhar-um-erro-49">Ignorando quando embrulhar um erro (#49)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Embrulhar um erro permite marcar um erro e/ou fornecer contexto adicional. No entanto, o agrupamento de erros cria um acoplamento potencial, pois disponibiliza o erro de origem para o chamador. Se você quiser evitar isso, não use a agrupamento automático de erros.</p>
</details>
<p>Since Go 1.13, the %w directive allows us to wrap errors conveniently. Error wrapping is about wrapping or packing an error inside a wrapper container that also makes the source error available. In general, the two main use cases for error wrapping are the following:</p>
<ul>
<li>Adding additional context to an error</li>
<li>Marking an error as a specific error</li>
</ul>
<p>When handling an error, we can decide to wrap it. Wrapping is about adding additional context to an error and/or marking an error as a specific type. If we need to mark an error, we should create a custom error type. However, if we just want to add extra context, we should use fmt.Errorf with the %w directive as it doesnt require creating a new error type. Yet, error wrapping creates potential coupling as it makes the source error available for the caller. If we want to prevent it, we shouldnt use error wrapping but error transformation, for example, using fmt.Errorf with the %v directive.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/49-error-wrapping/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="comparando-um-tipo-de-erro-de-forma-imprecisa-50">Comparando um tipo de erro de forma imprecisa (#50)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Se você usar o agrupamento de erros do Go 1.13 com a diretiva <code>%w</code> e <code>fmt.Errorf</code>, a comparação de um erro com um tipo deverá ser feita usando <code>errors.As</code>. Caso contrário, se o erro retornado que você deseja verificar for embrulhado, as verificações falharão.</p>
</details>
<!-- TODO -->
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/50-compare-error-type/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="comparando-um-valor-de-erro-incorretamente-51">Comparando um valor de erro incorretamente (#51)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Se você usar o agrupamento de erros do Go 1.13 com a diretiva <code>%w</code> e <code>fmt.Errorf</code>, a comparação de um erro ou de um valor deverá ser feita usando <code>errors.As</code>. Caso contrário, se o erro retornado que você deseja verificar for embrulhado, as verificações falharão.</p>
</details>
<p>A sentinel error is an error defined as a global variable:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-32-1"><a id="__codelineno-32-1" name="__codelineno-32-1" href="#__codelineno-32-1"></a><span class="kn">import</span><span class="w"> </span><span class="s">&quot;errors&quot;</span>
</span><span id="__span-32-2"><a id="__codelineno-32-2" name="__codelineno-32-2" href="#__codelineno-32-2"></a>
</span><span id="__span-32-3"><a id="__codelineno-32-3" name="__codelineno-32-3" href="#__codelineno-32-3"></a><span class="kd">var</span><span class="w"> </span><span class="nx">ErrFoo</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">errors</span><span class="p">.</span><span class="nx">New</span><span class="p">(</span><span class="s">&quot;foo&quot;</span><span class="p">)</span>
</span></code></pre></div>
<p>In general, the convention is to start with <code>Err</code> followed by the error type: here, <code>ErrFoo</code>. A sentinel error conveys an <em>expected</em> error, an error that clients will expect to check. As general guidelines:</p>
<ul>
<li>Expected errors should be designed as error values (sentinel errors): <code>var ErrFoo = errors.New("foo")</code>.</li>
<li>Unexpected errors should be designed as error types: <code>type BarError struct { ... }</code>, with <code>BarError</code> implementing the <code>error</code> interface.</li>
</ul>
<p>If we use error wrapping in our application with the <code>%w</code> directive and <code>fmt.Errorf</code>, checking an error against a specific value should be done using <code>errors.Is</code> instead of <code>==</code>. Thus, even if the sentinel error is wrapped, <code>errors.Is</code> can recursively unwrap it and compare each error in the chain against the provided value.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/51-comparing-error-value/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="lidando-com-um-erro-duas-vezes-52">Lidando com um erro duas vezes (#52)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Na maioria das situações, um erro deve ser tratado apenas uma vez. Registrar um erro é tratar um erro. Portanto, você deve escolher entre registrar ou retornar um erro. Em muitos casos, o embrulho automático de erros é a solução, pois permite fornecer contexto adicional a um erro e retornar o erro de origem.</p>
</details>
<p>Handling an error multiple times is a mistake made frequently by developers, not specifically in Go. This can cause situations where the same error is logged multiple times make debugging harder.</p>
<p>Let's remind us that handling an error should be done only once. Logging an error is handling an error. Hence, we should either log or return an error. By doing this, we simplify our code and gain better insights into the error situation. Using error wrapping is the most convenient approach as it allows us to propagate the source error and add context to an error.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/52-handling-error-twice/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="nao-tratando-de-um-erro-53">Não tratando de um erro (#53)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Ignorar um erro, seja durante uma chamada de função ou em uma função <code>defer</code>, deve ser feito explicitamente usando o identificador em branco. Caso contrário, os futuros leitores poderão ficar confusos sobre se foi intencional ou um erro.</p>
</details>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/53-not-handling-error/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="nao-tratando-erros-de-defer-54">Não tratando erros de <code>defer</code> (#54)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Em muitos casos, você não deve ignorar um erro retornado por uma função <code>defer</code>. Manipule-o diretamente ou propague-o para o chamador, dependendo do contexto. Se você quiser ignorá-lo, use o identificador em branco.</p>
</details>
<p>Consider the following code:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-33-1"><a id="__codelineno-33-1" name="__codelineno-33-1" href="#__codelineno-33-1"></a><span class="kd">func</span><span class="w"> </span><span class="nx">f</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-33-2"><a id="__codelineno-33-2" name="__codelineno-33-2" href="#__codelineno-33-2"></a><span class="w"> </span><span class="c1">// ...</span>
</span><span id="__span-33-3"><a id="__codelineno-33-3" name="__codelineno-33-3" href="#__codelineno-33-3"></a><span class="w"> </span><span class="nx">notify</span><span class="p">()</span><span class="w"> </span><span class="c1">// Error handling is omitted</span>
</span><span id="__span-33-4"><a id="__codelineno-33-4" name="__codelineno-33-4" href="#__codelineno-33-4"></a><span class="p">}</span>
</span><span id="__span-33-5"><a id="__codelineno-33-5" name="__codelineno-33-5" href="#__codelineno-33-5"></a>
</span><span id="__span-33-6"><a id="__codelineno-33-6" name="__codelineno-33-6" href="#__codelineno-33-6"></a><span class="kd">func</span><span class="w"> </span><span class="nx">notify</span><span class="p">()</span><span class="w"> </span><span class="kt">error</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-33-7"><a id="__codelineno-33-7" name="__codelineno-33-7" href="#__codelineno-33-7"></a><span class="w"> </span><span class="c1">// ...</span>
</span><span id="__span-33-8"><a id="__codelineno-33-8" name="__codelineno-33-8" href="#__codelineno-33-8"></a><span class="p">}</span>
</span></code></pre></div>
<p>From a maintainability perspective, the code can lead to some issues. Lets consider a new reader looking at it. This reader notices that notify returns an error but that the error isnt handled by the parent function. How can they guess whether or not handling the error was intentional? How can they know whether the previous developer forgot to handle it or did it purposely?</p>
<p>For these reasons, when we want to ignore an error, there's only one way to do it, using the blank identifier (<code>_</code>):</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-34-1"><a id="__codelineno-34-1" name="__codelineno-34-1" href="#__codelineno-34-1"></a><span class="nx">_</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">notify</span>
</span></code></pre></div>
<p>In terms of compilation and run time, this approach doesnt change anything compared to the first piece of code. But this new version makes explicit that we arent interested in the error. Also, we can add a comment that indicates the rationale for why an error is ignored:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-35-1"><a id="__codelineno-35-1" name="__codelineno-35-1" href="#__codelineno-35-1"></a><span class="c1">// At-most once delivery.</span>
</span><span id="__span-35-2"><a id="__codelineno-35-2" name="__codelineno-35-2" href="#__codelineno-35-2"></a><span class="c1">// Hence, it&#39;s accepted to miss some of them in case of errors.</span>
</span><span id="__span-35-3"><a id="__codelineno-35-3" name="__codelineno-35-3" href="#__codelineno-35-3"></a><span class="nx">_</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">notify</span><span class="p">()</span>
</span></code></pre></div>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/54-defer-errors/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h2 id="concurrency-foundations">Concurrency: Foundations</h2>
<h3 id="misturando-simultaneidade-e-paralelismo-55">Misturando simultaneidade e paralelismo (#55)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Compreender as diferenças fundamentais entre simultaneidade e paralelismo é a base do conhecimento do desenvolvedor Go. A simultaneidade tem a ver com estrutura, enquanto o paralelismo tem a ver com execução.</p>
</details>
<p>Concurrency and parallelism are not the same:</p>
<ul>
<li>Concurrency is about structure. We can change a sequential implementation into a concurrent one by introducing different steps that separate concurrent goroutines can tackle.</li>
<li>Meanwhile, parallelism is about execution. We can use parallism at the steps level by adding more parallel goroutines.</li>
</ul>
<p>In summary, concurrency provides a structure to solve a problem with parts that may be parallelized. Therefore, <em>concurrency enables parallelism</em>.</p>
<!-- TODO Include Rob Pike's talk link-->
<h3 id="pensar-que-a-simultaneidade-e-sempre-mais-rapida-56">Pensar que a simultaneidade é sempre mais rápida (#56)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Para ser um desenvolvedor proficiente, você deve reconhecer que a simultaneidade nem sempre é mais rápida. As soluções que envolvem a paralelização de cargas de trabalho mínimas podem não ser necessariamente mais rápidas do que uma implementação sequencial. A avaliação comparativa de soluções sequenciais versus soluções simultâneas deve ser a forma de validar suposições.</p>
</details>
<p>Read the full section <a href="../56-concurrency-faster/">here</a>.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/08-concurrency-foundations/56-faster/"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="ficar-confuso-sobre-quando-usar-canais-ou-mutexes-57">Ficar confuso sobre quando usar canais ou mutexes (#57)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Estar ciente das interações goroutine também pode ser útil ao decidir entre canais e mutexes. Em geral, goroutines paralelas requerem sincronização e, portanto, mutexes. Por outro lado, goroutines simultâneas geralmente requerem coordenação e orquestração e, portanto, canais.</p>
</details>
<p>Given a concurrency problem, it may not always be clear whether we can implement a
solution using channels or mutexes. Because Go promotes sharing memory by communication, one mistake could be to always force the use of channels, regardless of
the use case. However, we should see the two options as complementary. </p>
<p>When should we use channels or mutexes? We will use the example in the next figure as a backbone. Our example has three different goroutines with specific relationships:</p>
<ul>
<li>G1 and G2 are parallel goroutines. They may be two goroutines executing the same function that keeps receiving messages from a channel, or perhaps two goroutines executing the same HTTP handler at the same time.</li>
<li>On the other hand, G1 and G3 are concurrent goroutines, as are G2 and G3. All the goroutines are part of an overall concurrent structure, but G1 and G2 perform the first step, whereas G3 does the next step.</li>
</ul>
<!-- TODO Include figure-->
<p>In general, parallel goroutines have to <em>synchronize</em>: for example, when they need to access or mutate a shared resource such as a slice. Synchronization is enforced with mutexes but not with any channel types (not with buffered channels). Hence, in general, synchronization between parallel goroutines should be achieved via mutexes.</p>
<p>Conversely, in general, concurrent goroutines have to <em>coordinate and orchestrate</em>. For example, if G3 needs to aggregate results from both G1 and G2, G1 and G2 need to signal to G3 that a new intermediate result is available. This coordination falls under the scope of communication—therefore, channels.</p>
<p>Regarding concurrent goroutines, theres also the case where we want to transfer the ownership of a resource from one step (G1 and G2) to another (G3); for example, if G1 and G2 are enriching a shared resource and at some point, we consider this job as complete. Here, we should use channels to signal that a specific resource is ready and handle the ownership transfer.</p>
<p>Mutexes and channels have different semantics. Whenever we want to share a state or access a shared resource, mutexes ensure exclusive access to this resource. Conversely, channels are a mechanic for signaling with or without data (<code>chan struct{}</code> or not). Coordination or ownership transfer should be achieved via channels. Its important to know whether goroutines are parallel or concurrent because, in general, we need mutexes for parallel goroutines and channels for concurrent ones.</p>
<h3 id="nao-entender-os-problemas-de-corrida-corridas-de-dados-vs-condicoes-de-corrida-e-o-modelo-de-memoria-go-58">Não entender os problemas de corrida (corridas de dados vs. condições de corrida e o modelo de memória Go) (#58)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Ser proficiente em simultaneidade também significa compreender que corridas de dados e condições de corrida são conceitos diferentes. As corridas de dados ocorrem quando várias goroutines acessam simultaneamente o mesmo local de memória e pelo menos uma delas está gravando. Enquanto isso, estar livre de disputa de dados não significa necessariamente execução determinística. Quando um comportamento depende da sequência ou do tempo de eventos que não podem ser controlados, esta é uma condição de corrida.</p>
</details>
<p>Race problems can be among the hardest and most insidious bugs a programmer can face. As Go developers, we must understand crucial aspects such as data races and race conditions, their possible impacts, and how to avoid them.</p>
<h4 id="data-race">Data Race</h4>
<p>A data race occurs when two or more goroutines simultaneously access the same memory location and at least one is writing. In this case, the result can be hazardous. Even worse, in some situations, the memory location may end up holding a value containing a meaningless combination of bits.</p>
<p>We can prevent a data race from happening using different techniques. For example: </p>
<ul>
<li>Using the <code>sync/atomic</code> package</li>
<li>In synchronizing the two goroutines with an ad hoc data structure like a mutex</li>
<li>Using channels to make the two goroutines communicating to ensure that a variable is updated by only one goroutine at a time</li>
</ul>
<h4 id="race-condition">Race Condition</h4>
<p>Depending on the operation we want to perform, does a data-race-free application necessarily mean a deterministic result? Not necessarily.</p>
<p>A race condition occurs when the behavior depends on the sequence or the timing of events that cant be controlled. Here, the timing of events is the goroutines execution order.</p>
<p>In summary, when we work in concurrent applications, its essential to understand that a data race is different from a race condition. A data race occurs when multiple goroutines simultaneously access the same memory location and at least one of them is writing. A data race means unexpected behavior. However, a data-race-free application doesnt necessarily mean deterministic results. An application can be free of data races but still have behavior that depends on uncontrolled events (such as goroutine execution, how fast a message is published to a channel, or how long a call to a database lasts); this is a race condition. Understanding both concepts is crucial to becoming proficient in designing concurrent applications.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/08-concurrency-foundations/58-races/"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="nao-compreender-os-impactos-de-simultaneidade-de-um-tipo-de-carga-de-trabalho-59">Não compreender os impactos de simultaneidade de um tipo de carga de trabalho (#59)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Ao criar um determinado número de goroutines, considere o tipo de carga de trabalho. Criar goroutines vinculadas à CPU significa limitar esse número próximo à variável <abbr title="The variable defines the limit of OS threads in charge of executing user-level code simultaneously">GOMAXPROCS</abbr> (baseado por padrão no número de núcleos de CPU no host). A criação de goroutines vinculadas a E/S depende de outros fatores, como o sistema externo.</p>
</details>
<p>In programming, the execution time of a workload is limited by one of the following:</p>
<ul>
<li>The speed of the CPU—For example, running a merge sort algorithm. The workload is called CPU-bound.</li>
<li>The speed of I/O—For example, making a REST call or a database query. The workload is called I/O-bound.</li>
<li>The amount of available memory—The workload is called memory-bound.</li>
</ul>
<details class="note" open="open">
<summary>Note</summary>
<p>The last is the rarest nowadays, given that memory has become very cheap in recent decades. Hence, this section focuses on the two first workload types: CPU- and I/O-bound.</p>
</details>
<p>If the workload executed by the workers is I/O-bound, the value mainly depends on the external system. Conversely, if the workload is CPU-bound, the optimal number of goroutines is close to the number of available CPU cores (a best practice can be to use <code>runtime.GOMAXPROCS</code>). Knowing the workload type (I/O or CPU) is crucial when designing concurrent applications.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/08-concurrency-foundations/59-workload-type/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="incompreensao-dos-contextos-go-60">Incompreensão dos contextos Go (#60)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Os contextos Go também são um dos pilares da simultaneidade em Go. Um contexto permite que você carregue um prazo, um sinal de cancelamento e/ou uma lista de valores-chave.</p>
</details>
<div class="admonition quote">
<p class="admonition-title">https://pkg.go.dev/context</p>
<p>A Context carries a deadline, a cancellation signal, and other values across API boundaries.</p>
</div>
<h4 id="deadline">Deadline</h4>
<p>A deadline refers to a specific point in time determined with one of the following:</p>
<ul>
<li>A <code>time.Duration</code> from now (for example, in 250 ms)</li>
<li>A <code>time.Time</code> (for example, 2023-02-07 00:00:00 UTC)</li>
</ul>
<p>The semantics of a deadline convey that an ongoing activity should be stopped if this deadline is met. An activity is, for example, an I/O request or a goroutine waiting to receive a message from a channel.</p>
<h4 id="cancellation-signals">Cancellation signals</h4>
<p>Another use case for Go contexts is to carry a cancellation signal. Lets imagine that we want to create an application that calls <code>CreateFileWatcher(ctx context.Context, filename string)</code> within another goroutine. This function creates a specific file watcher that keeps reading from a file and catches updates. When the provided context expires or is canceled, this function handles it to close the file descriptor.</p>
<h4 id="context-values">Context values</h4>
<p>The last use case for Go contexts is to carry a key-value list. Whats the point of having a context carrying a key-value list? Because Go contexts are generic and mainstream, there are infinite use cases.</p>
<p>For example, if we use tracing, we may want different subfunctions to share the same correlation ID. Some developers may consider this ID too invasive to be part of the function signature. In this regard, we could also decide to include it as part of the provided context.</p>
<h4 id="catching-a-context-cancellation">Catching a context cancellation</h4>
<p>The <code>context.Context</code> type exports a <code>Done</code> method that returns a receive-only notification channel: <code>&lt;-chan struct{}</code>. This channel is closed when the work associated with the context should be canceled. For example,</p>
<ul>
<li>The Done channel related to a context created with <code>context.WithCancel</code> is closed when the cancel function is called.</li>
<li>The Done channel related to a context created with <code>context.WithDeadline</code> is closed when the deadline has expired.</li>
</ul>
<p>One thing to note is that the internal channel should be closed when a context is canceled or has met a deadline, instead of when it receives a specific value, because the closure of a channel is the only channel action that all the consumer goroutines will receive. This way, all the consumers will be notified once a context is canceled or a deadline is reached.</p>
<p>In summary, to be a proficient Go developer, we have to understand what a context is and how to use it. In general, a function that users wait for should take a context, as doing so allows upstream callers to decide when calling this function should be aborted. </p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/08-concurrency-foundations/60-contexts/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h2 id="concurrency-practice">Concurrency: Practice</h2>
<h3 id="propagando-um-contexto-improprio-61">Propagando um contexto impróprio (#61)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Compreender as condições em que um contexto pode ser cancelado deve ser importante ao propagá-lo: por exemplo, um manipulador HTTP cancelando o contexto quando a resposta for enviada.</p>
</details>
<p>In many situations, it is recommended to propagate Go contexts. However, context propagation can sometimes lead to subtle bugs, preventing subfunctions from being correctly executed.</p>
<p>Lets consider the following example. We expose an HTTP handler that performs some tasks and returns a response. But just before returning the response, we also want to send it to a Kafka topic. We dont want to penalize the HTTP consumer latency-wise, so we want the publish action to be handled asynchronously within a new goroutine. We assume that we have at our disposal a <code>publish</code> function that accepts a context so the action of publishing a message can be interrupted if the context is canceled, for example. Here is a possible implementation:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-36-1"><a id="__codelineno-36-1" name="__codelineno-36-1" href="#__codelineno-36-1"></a><span class="kd">func</span><span class="w"> </span><span class="nx">handler</span><span class="p">(</span><span class="nx">w</span><span class="w"> </span><span class="nx">http</span><span class="p">.</span><span class="nx">ResponseWriter</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">*</span><span class="nx">http</span><span class="p">.</span><span class="nx">Request</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-36-2"><a id="__codelineno-36-2" name="__codelineno-36-2" href="#__codelineno-36-2"></a><span class="w"> </span><span class="nx">response</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">doSomeTask</span><span class="p">(</span><span class="nx">r</span><span class="p">.</span><span class="nx">Context</span><span class="p">(),</span><span class="w"> </span><span class="nx">r</span><span class="p">)</span>
</span><span id="__span-36-3"><a id="__codelineno-36-3" name="__codelineno-36-3" href="#__codelineno-36-3"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-36-4"><a id="__codelineno-36-4" name="__codelineno-36-4" href="#__codelineno-36-4"></a><span class="w"> </span><span class="nx">http</span><span class="p">.</span><span class="nx">Error</span><span class="p">(</span><span class="nx">w</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="p">.</span><span class="nx">Error</span><span class="p">(),</span><span class="w"> </span><span class="nx">http</span><span class="p">.</span><span class="nx">StatusInternalServerError</span><span class="p">)</span>
</span><span id="__span-36-5"><a id="__codelineno-36-5" name="__codelineno-36-5" href="#__codelineno-36-5"></a><span class="w"> </span><span class="k">return</span>
</span><span id="__span-36-6"><a id="__codelineno-36-6" name="__codelineno-36-6" href="#__codelineno-36-6"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-36-7"><a id="__codelineno-36-7" name="__codelineno-36-7" href="#__codelineno-36-7"></a><span class="w"> </span><span class="k">go</span><span class="w"> </span><span class="kd">func</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-36-8"><a id="__codelineno-36-8" name="__codelineno-36-8" href="#__codelineno-36-8"></a><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">publish</span><span class="p">(</span><span class="nx">r</span><span class="p">.</span><span class="nx">Context</span><span class="p">(),</span><span class="w"> </span><span class="nx">response</span><span class="p">)</span>
</span><span id="__span-36-9"><a id="__codelineno-36-9" name="__codelineno-36-9" href="#__codelineno-36-9"></a><span class="w"> </span><span class="c1">// Do something with err</span>
</span><span id="__span-36-10"><a id="__codelineno-36-10" name="__codelineno-36-10" href="#__codelineno-36-10"></a><span class="w"> </span><span class="p">}()</span>
</span><span id="__span-36-11"><a id="__codelineno-36-11" name="__codelineno-36-11" href="#__codelineno-36-11"></a><span class="w"> </span><span class="nx">writeResponse</span><span class="p">(</span><span class="nx">response</span><span class="p">)</span>
</span><span id="__span-36-12"><a id="__codelineno-36-12" name="__codelineno-36-12" href="#__codelineno-36-12"></a><span class="p">}</span>
</span></code></pre></div>
<p>Whats wrong with this piece of code? We have to know that the context attached to an HTTP request can cancel in different conditions:</p>
<ul>
<li>When the clients connection closes</li>
<li>In the case of an HTTP/2 request, when the request is canceled</li>
<li>When the response has been written back to the client</li>
</ul>
<p>In the first two cases, we probably handle things correctly. For example, if we get a response from doSomeTask but the client has closed the connection, its probably OK to call publish with a context already canceled so the message isnt published. But what about the last case?</p>
<p>When the response has been written to the client, the context associated with the request will be canceled. Therefore, we are facing a race condition:</p>
<ul>
<li>If the response is written after the Kafka publication, we both return a response and publish a message successfully</li>
<li>However, if the response is written before or during the Kafka publication, the message shouldnt be published.</li>
</ul>
<p>In the latter case, calling publish will return an error because we returned the HTTP response quickly.</p>
<details class="note" open="open">
<summary>Note</summary>
<p>From Go 1.21, there is a way to create a new context without cancel. <a href="https://pkg.go.dev/context#WithoutCancel"><code>context.WithoutCancel</code></a> returns a copy of parent that is not canceled when parent is canceled.</p>
</details>
<p>In summary, propagating a context should be done cautiously.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/61-inappropriate-context/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="iniciando-uma-goroutine-sem-saber-quando-interrompe-la-62">Iniciando uma goroutine sem saber quando interrompê-la (#62)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Evitar vazamentos significa estar ciente de que sempre que uma goroutine for iniciada, você deve ter um plano para interrompê-la eventualmente.</p>
</details>
<p>Goroutines are easy and cheap to start—so easy and cheap that we may not necessarily have a plan for when to stop a new goroutine, which can lead to leaks. Not knowing when to stop a goroutine is a design issue and a common concurrency mistake in Go.</p>
<p>Lets discuss a concrete example. We will design an application that needs to watch some external configuration (for example, using a database connection). Heres a first implementation:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-37-1"><a id="__codelineno-37-1" name="__codelineno-37-1" href="#__codelineno-37-1"></a><span class="kd">func</span><span class="w"> </span><span class="nx">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-37-2"><a id="__codelineno-37-2" name="__codelineno-37-2" href="#__codelineno-37-2"></a><span class="w"> </span><span class="nx">newWatcher</span><span class="p">()</span>
</span><span id="__span-37-3"><a id="__codelineno-37-3" name="__codelineno-37-3" href="#__codelineno-37-3"></a><span class="w"> </span><span class="c1">// Run the application</span>
</span><span id="__span-37-4"><a id="__codelineno-37-4" name="__codelineno-37-4" href="#__codelineno-37-4"></a><span class="p">}</span>
</span><span id="__span-37-5"><a id="__codelineno-37-5" name="__codelineno-37-5" href="#__codelineno-37-5"></a>
</span><span id="__span-37-6"><a id="__codelineno-37-6" name="__codelineno-37-6" href="#__codelineno-37-6"></a><span class="kd">type</span><span class="w"> </span><span class="nx">watcher</span><span class="w"> </span><span class="kd">struct</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* Some resources */</span><span class="w"> </span><span class="p">}</span>
</span><span id="__span-37-7"><a id="__codelineno-37-7" name="__codelineno-37-7" href="#__codelineno-37-7"></a>
</span><span id="__span-37-8"><a id="__codelineno-37-8" name="__codelineno-37-8" href="#__codelineno-37-8"></a><span class="kd">func</span><span class="w"> </span><span class="nx">newWatcher</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-37-9"><a id="__codelineno-37-9" name="__codelineno-37-9" href="#__codelineno-37-9"></a><span class="w"> </span><span class="nx">w</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">watcher</span><span class="p">{}</span>
</span><span id="__span-37-10"><a id="__codelineno-37-10" name="__codelineno-37-10" href="#__codelineno-37-10"></a><span class="w"> </span><span class="k">go</span><span class="w"> </span><span class="nx">w</span><span class="p">.</span><span class="nx">watch</span><span class="p">()</span><span class="w"> </span><span class="c1">// Creates a goroutine that watches some external configuration</span>
</span><span id="__span-37-11"><a id="__codelineno-37-11" name="__codelineno-37-11" href="#__codelineno-37-11"></a><span class="p">}</span>
</span></code></pre></div>
<p>The problem with this code is that when the main goroutine exits (perhaps because of an OS signal or because it has a finite workload), the application is stopped. Hence, the resources created by watcher arent closed gracefully. How can we prevent this from happening?</p>
<p>One option could be to pass to newWatcher a context that will be canceled when main returns:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-38-1"><a id="__codelineno-38-1" name="__codelineno-38-1" href="#__codelineno-38-1"></a><span class="kd">func</span><span class="w"> </span><span class="nx">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-38-2"><a id="__codelineno-38-2" name="__codelineno-38-2" href="#__codelineno-38-2"></a><span class="w"> </span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="nx">cancel</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">WithCancel</span><span class="p">(</span><span class="nx">context</span><span class="p">.</span><span class="nx">Background</span><span class="p">())</span>
</span><span id="__span-38-3"><a id="__codelineno-38-3" name="__codelineno-38-3" href="#__codelineno-38-3"></a><span class="w"> </span><span class="k">defer</span><span class="w"> </span><span class="nx">cancel</span><span class="p">()</span>
</span><span id="__span-38-4"><a id="__codelineno-38-4" name="__codelineno-38-4" href="#__codelineno-38-4"></a><span class="w"> </span><span class="nx">newWatcher</span><span class="p">(</span><span class="nx">ctx</span><span class="p">)</span>
</span><span id="__span-38-5"><a id="__codelineno-38-5" name="__codelineno-38-5" href="#__codelineno-38-5"></a><span class="w"> </span><span class="c1">// Run the application</span>
</span><span id="__span-38-6"><a id="__codelineno-38-6" name="__codelineno-38-6" href="#__codelineno-38-6"></a><span class="p">}</span>
</span><span id="__span-38-7"><a id="__codelineno-38-7" name="__codelineno-38-7" href="#__codelineno-38-7"></a>
</span><span id="__span-38-8"><a id="__codelineno-38-8" name="__codelineno-38-8" href="#__codelineno-38-8"></a><span class="kd">func</span><span class="w"> </span><span class="nx">newWatcher</span><span class="p">(</span><span class="nx">ctx</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">Context</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-38-9"><a id="__codelineno-38-9" name="__codelineno-38-9" href="#__codelineno-38-9"></a><span class="w"> </span><span class="nx">w</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">watcher</span><span class="p">{}</span>
</span><span id="__span-38-10"><a id="__codelineno-38-10" name="__codelineno-38-10" href="#__codelineno-38-10"></a><span class="w"> </span><span class="k">go</span><span class="w"> </span><span class="nx">w</span><span class="p">.</span><span class="nx">watch</span><span class="p">(</span><span class="nx">ctx</span><span class="p">)</span>
</span><span id="__span-38-11"><a id="__codelineno-38-11" name="__codelineno-38-11" href="#__codelineno-38-11"></a><span class="p">}</span>
</span></code></pre></div>
<p>We propagate the context created to the watch method. When the context is canceled, the watcher struct should close its resources. However, can we guarantee that watch will have time to do so? Absolutely not—and thats a design flaw.</p>
<p>The problem is that we used signaling to convey that a goroutine had to be stopped. We didnt block the parent goroutine until the resources had been closed. Lets make sure we do:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-39-1"><a id="__codelineno-39-1" name="__codelineno-39-1" href="#__codelineno-39-1"></a><span class="kd">func</span><span class="w"> </span><span class="nx">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-39-2"><a id="__codelineno-39-2" name="__codelineno-39-2" href="#__codelineno-39-2"></a><span class="w"> </span><span class="nx">w</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">newWatcher</span><span class="p">()</span>
</span><span id="__span-39-3"><a id="__codelineno-39-3" name="__codelineno-39-3" href="#__codelineno-39-3"></a><span class="w"> </span><span class="k">defer</span><span class="w"> </span><span class="nx">w</span><span class="p">.</span><span class="nb">close</span><span class="p">()</span>
</span><span id="__span-39-4"><a id="__codelineno-39-4" name="__codelineno-39-4" href="#__codelineno-39-4"></a><span class="w"> </span><span class="c1">// Run the application</span>
</span><span id="__span-39-5"><a id="__codelineno-39-5" name="__codelineno-39-5" href="#__codelineno-39-5"></a><span class="p">}</span>
</span><span id="__span-39-6"><a id="__codelineno-39-6" name="__codelineno-39-6" href="#__codelineno-39-6"></a>
</span><span id="__span-39-7"><a id="__codelineno-39-7" name="__codelineno-39-7" href="#__codelineno-39-7"></a><span class="kd">func</span><span class="w"> </span><span class="nx">newWatcher</span><span class="p">()</span><span class="w"> </span><span class="nx">watcher</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-39-8"><a id="__codelineno-39-8" name="__codelineno-39-8" href="#__codelineno-39-8"></a><span class="w"> </span><span class="nx">w</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">watcher</span><span class="p">{}</span>
</span><span id="__span-39-9"><a id="__codelineno-39-9" name="__codelineno-39-9" href="#__codelineno-39-9"></a><span class="w"> </span><span class="k">go</span><span class="w"> </span><span class="nx">w</span><span class="p">.</span><span class="nx">watch</span><span class="p">()</span>
</span><span id="__span-39-10"><a id="__codelineno-39-10" name="__codelineno-39-10" href="#__codelineno-39-10"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">w</span>
</span><span id="__span-39-11"><a id="__codelineno-39-11" name="__codelineno-39-11" href="#__codelineno-39-11"></a><span class="p">}</span>
</span><span id="__span-39-12"><a id="__codelineno-39-12" name="__codelineno-39-12" href="#__codelineno-39-12"></a>
</span><span id="__span-39-13"><a id="__codelineno-39-13" name="__codelineno-39-13" href="#__codelineno-39-13"></a><span class="kd">func</span><span class="w"> </span><span class="p">(</span><span class="nx">w</span><span class="w"> </span><span class="nx">watcher</span><span class="p">)</span><span class="w"> </span><span class="nb">close</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-39-14"><a id="__codelineno-39-14" name="__codelineno-39-14" href="#__codelineno-39-14"></a><span class="w"> </span><span class="c1">// Close the resources</span>
</span><span id="__span-39-15"><a id="__codelineno-39-15" name="__codelineno-39-15" href="#__codelineno-39-15"></a><span class="p">}</span>
</span></code></pre></div>
<p>Instead of signaling <code>watcher</code> that its time to close its resources, we now call this <code>close</code> method, using <code>defer</code> to guarantee that the resources are closed before the application exits.</p>
<p>In summary, lets be mindful that a goroutine is a resource like any other that must eventually be closed to free memory or other resources. Starting a goroutine without knowing when to stop it is a design issue. Whenever a goroutine is started, we should have a clear plan about when it will stop. Last but not least, if a goroutine creates resources and its lifetime is bound to the lifetime of the application, its probably safer to wait for this goroutine to complete before exiting the application. This way, we can ensure that the resources can be freed.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/62-starting-goroutine/"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="nao-ter-cuidado-com-goroutines-e-variaveis-de-loop-63"><img alt="⚠" class="twemoji" src="https://cdn.jsdelivr.net/gh/jdecked/twemoji@15.0.3/assets/svg/26a0.svg" title=":warning:" /> Não ter cuidado com goroutines e variáveis de loop (#63)</h3>
<details class="warning" open="open">
<summary>Warning</summary>
<p>Este erro não é mais relevante no Go 1.22 (<a href="https://go.dev/blog/loopvar-preview">detalhes</a>).</p>
</details>
<h3 id="esperando-um-comportamento-deterministico-usando-selecao-e-canais-64">Esperando um comportamento determinístico usando seleção e canais (#64)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Compreender que com <code>select</code> vários canais escolhe o caso aleatoriamente se múltiplas opções forem possíveis evita fazer suposições erradas que podem levar a erros sutis de simultaneidade.</p>
</details>
<p>One common mistake made by Go developers while working with channels is to make wrong assumptions about how select behaves with multiple channels.</p>
<p>For example, let's consider the following case (<code>disconnectCh</code> is a unbuffered channel):</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-40-1"><a id="__codelineno-40-1" name="__codelineno-40-1" href="#__codelineno-40-1"></a><span class="k">go</span><span class="w"> </span><span class="kd">func</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-40-2"><a id="__codelineno-40-2" name="__codelineno-40-2" href="#__codelineno-40-2"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="p">&lt;</span><span class="w"> </span><span class="mi">10</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-40-3"><a id="__codelineno-40-3" name="__codelineno-40-3" href="#__codelineno-40-3"></a><span class="w"> </span><span class="nx">messageCh</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="nx">i</span>
</span><span id="__span-40-4"><a id="__codelineno-40-4" name="__codelineno-40-4" href="#__codelineno-40-4"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-40-5"><a id="__codelineno-40-5" name="__codelineno-40-5" href="#__codelineno-40-5"></a><span class="w"> </span><span class="nx">disconnectCh</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="kd">struct</span><span class="p">{}{}</span>
</span><span id="__span-40-6"><a id="__codelineno-40-6" name="__codelineno-40-6" href="#__codelineno-40-6"></a><span class="p">}()</span>
</span><span id="__span-40-7"><a id="__codelineno-40-7" name="__codelineno-40-7" href="#__codelineno-40-7"></a>
</span><span id="__span-40-8"><a id="__codelineno-40-8" name="__codelineno-40-8" href="#__codelineno-40-8"></a><span class="k">for</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-40-9"><a id="__codelineno-40-9" name="__codelineno-40-9" href="#__codelineno-40-9"></a><span class="w"> </span><span class="k">select</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-40-10"><a id="__codelineno-40-10" name="__codelineno-40-10" href="#__codelineno-40-10"></a><span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="nx">v</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="o">&lt;-</span><span class="nx">messageCh</span><span class="p">:</span>
</span><span id="__span-40-11"><a id="__codelineno-40-11" name="__codelineno-40-11" href="#__codelineno-40-11"></a><span class="w"> </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="nx">v</span><span class="p">)</span>
</span><span id="__span-40-12"><a id="__codelineno-40-12" name="__codelineno-40-12" href="#__codelineno-40-12"></a><span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="o">&lt;-</span><span class="nx">disconnectCh</span><span class="p">:</span>
</span><span id="__span-40-13"><a id="__codelineno-40-13" name="__codelineno-40-13" href="#__codelineno-40-13"></a><span class="w"> </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="s">&quot;disconnection, return&quot;</span><span class="p">)</span>
</span><span id="__span-40-14"><a id="__codelineno-40-14" name="__codelineno-40-14" href="#__codelineno-40-14"></a><span class="w"> </span><span class="k">return</span>
</span><span id="__span-40-15"><a id="__codelineno-40-15" name="__codelineno-40-15" href="#__codelineno-40-15"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-40-16"><a id="__codelineno-40-16" name="__codelineno-40-16" href="#__codelineno-40-16"></a><span class="p">}</span>
</span></code></pre></div>
<p>If we run this example multiple times, the result will be random:</p>
<div class="language-text highlight"><pre><span></span><code><span id="__span-41-1"><a id="__codelineno-41-1" name="__codelineno-41-1" href="#__codelineno-41-1"></a>0
</span><span id="__span-41-2"><a id="__codelineno-41-2" name="__codelineno-41-2" href="#__codelineno-41-2"></a>1
</span><span id="__span-41-3"><a id="__codelineno-41-3" name="__codelineno-41-3" href="#__codelineno-41-3"></a>2
</span><span id="__span-41-4"><a id="__codelineno-41-4" name="__codelineno-41-4" href="#__codelineno-41-4"></a>disconnection, return
</span><span id="__span-41-5"><a id="__codelineno-41-5" name="__codelineno-41-5" href="#__codelineno-41-5"></a>
</span><span id="__span-41-6"><a id="__codelineno-41-6" name="__codelineno-41-6" href="#__codelineno-41-6"></a>0
</span><span id="__span-41-7"><a id="__codelineno-41-7" name="__codelineno-41-7" href="#__codelineno-41-7"></a>disconnection, return
</span></code></pre></div>
<p>Instead of consuming the 10 messages, we only received a few of them. Whats the reason? It lies in the specification of the select statement with multiple channels (https:// go.dev/ref/spec):</p>
<div class="admonition quote">
<p class="admonition-title">Quote</p>
<p>If one or more of the communications can proceed, a single one that can proceed is chosen via a uniform pseudo-random selection.</p>
</div>
<p>Unlike a switch statement, where the first case with a match wins, the select statement selects randomly if multiple options are possible.</p>
<p>This behavior might look odd at first, but theres a good reason for it: to prevent possible starvation. Suppose the first possible communication chosen is based on the source order. In that case, we may fall into a situation where, for example, we only receive from one channel because of a fast sender. To prevent this, the language designers decided to use a random selection.</p>
<p>When using <code>select</code> with multiple channels, we must remember that if multiple options are possible, the first case in the source order does not automatically win. Instead, Go selects randomly, so theres no guarantee about which option will be chosen. To overcome this behavior, in the case of a single producer goroutine, we can use either unbuffered channels or a single channel.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/64-select-behavior/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="nao-usar-canais-de-notificacao-65">Não usar canais de notificação (#65)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Envie notificações usando um tipo <code>chan struct{}</code>.</p>
</details>
<p>Channels are a mechanism for communicating across goroutines via signaling. A signal can be either with or without data.</p>
<p>Lets look at a concrete example. We will create a channel that will notify us whenever a certain disconnection occurs. One idea is to handle it as a <code>chan bool</code>:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-42-1"><a id="__codelineno-42-1" name="__codelineno-42-1" href="#__codelineno-42-1"></a><span class="nx">disconnectCh</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nb">make</span><span class="p">(</span><span class="kd">chan</span><span class="w"> </span><span class="kt">bool</span><span class="p">)</span>
</span></code></pre></div>
<p>Now, lets say we interact with an API that provides us with such a channel. Because its a channel of Booleans, we can receive either <code>true</code> or <code>false</code> messages. Its probably clear what <code>true</code> conveys. But what does <code>false</code> mean? Does it mean we havent been disconnected? And in this case, how frequently will we receive such a signal? Does it mean we have reconnected? Should we even expect to receive <code>false</code>? Perhaps we should only expect to receive <code>true</code> messages.</p>
<p>If thats the case, meaning we dont need a specific value to convey some information, we need a channel <em>without</em> data. The idiomatic way to handle it is a channel of empty structs: <code>chan struct{}</code>.</p>
<h3 id="nao-usar-canais-nulos-66">Não usar canais nulos (#66)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>O uso de canais nulos deve fazer parte do seu conjunto de ferramentas de simultaneidade porque permite remover casos de instruções <code>select</code>, por exemplo.</p>
</details>
<p>What should this code do?</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-43-1"><a id="__codelineno-43-1" name="__codelineno-43-1" href="#__codelineno-43-1"></a><span class="kd">var</span><span class="w"> </span><span class="nx">ch</span><span class="w"> </span><span class="kd">chan</span><span class="w"> </span><span class="kt">int</span>
</span><span id="__span-43-2"><a id="__codelineno-43-2" name="__codelineno-43-2" href="#__codelineno-43-2"></a><span class="o">&lt;-</span><span class="nx">ch</span>
</span></code></pre></div>
<p><code>ch</code> is a <code>chan int</code> type. The zero value of a channel being nil, <code>ch</code> is <code>nil</code>. The goroutine wont panic; however, it will block forever.</p>
<p>The principle is the same if we send a message to a nil channel. This goroutine blocks forever:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-44-1"><a id="__codelineno-44-1" name="__codelineno-44-1" href="#__codelineno-44-1"></a><span class="kd">var</span><span class="w"> </span><span class="nx">ch</span><span class="w"> </span><span class="kd">chan</span><span class="w"> </span><span class="kt">int</span>
</span><span id="__span-44-2"><a id="__codelineno-44-2" name="__codelineno-44-2" href="#__codelineno-44-2"></a><span class="nx">ch</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="mi">0</span>
</span></code></pre></div>
<p>Then whats the purpose of Go allowing messages to be received from or sent to a nil channel? For example, we can use nil channels to implement an idiomatic way to merge two channels:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-45-1"><a id="__codelineno-45-1" name="__codelineno-45-1" href="#__codelineno-45-1"></a><span class="kd">func</span><span class="w"> </span><span class="nx">merge</span><span class="p">(</span><span class="nx">ch1</span><span class="p">,</span><span class="w"> </span><span class="nx">ch2</span><span class="w"> </span><span class="o">&lt;-</span><span class="kd">chan</span><span class="w"> </span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="o">&lt;-</span><span class="kd">chan</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-45-2"><a id="__codelineno-45-2" name="__codelineno-45-2" href="#__codelineno-45-2"></a><span class="w"> </span><span class="nx">ch</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nb">make</span><span class="p">(</span><span class="kd">chan</span><span class="w"> </span><span class="kt">int</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span>
</span><span id="__span-45-3"><a id="__codelineno-45-3" name="__codelineno-45-3" href="#__codelineno-45-3"></a>
</span><span id="__span-45-4"><a id="__codelineno-45-4" name="__codelineno-45-4" href="#__codelineno-45-4"></a><span class="w"> </span><span class="k">go</span><span class="w"> </span><span class="kd">func</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-45-5"><a id="__codelineno-45-5" name="__codelineno-45-5" href="#__codelineno-45-5"></a><span class="hll"><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="nx">ch1</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="nx">ch2</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="c1">// Continue if at least one channel isnt nil</span>
</span></span><span id="__span-45-6"><a id="__codelineno-45-6" name="__codelineno-45-6" href="#__codelineno-45-6"></a><span class="w"> </span><span class="k">select</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-45-7"><a id="__codelineno-45-7" name="__codelineno-45-7" href="#__codelineno-45-7"></a><span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="nx">v</span><span class="p">,</span><span class="w"> </span><span class="nx">open</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="o">&lt;-</span><span class="nx">ch1</span><span class="p">:</span>
</span><span id="__span-45-8"><a id="__codelineno-45-8" name="__codelineno-45-8" href="#__codelineno-45-8"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">!</span><span class="nx">open</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-45-9"><a id="__codelineno-45-9" name="__codelineno-45-9" href="#__codelineno-45-9"></a><span class="hll"><span class="w"> </span><span class="nx">ch1</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="c1">// Assign ch1 to a nil channel once closed</span>
</span></span><span id="__span-45-10"><a id="__codelineno-45-10" name="__codelineno-45-10" href="#__codelineno-45-10"></a><span class="w"> </span><span class="k">break</span>
</span><span id="__span-45-11"><a id="__codelineno-45-11" name="__codelineno-45-11" href="#__codelineno-45-11"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-45-12"><a id="__codelineno-45-12" name="__codelineno-45-12" href="#__codelineno-45-12"></a><span class="w"> </span><span class="nx">ch</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="nx">v</span>
</span><span id="__span-45-13"><a id="__codelineno-45-13" name="__codelineno-45-13" href="#__codelineno-45-13"></a><span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="nx">v</span><span class="p">,</span><span class="w"> </span><span class="nx">open</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="o">&lt;-</span><span class="nx">ch2</span><span class="p">:</span>
</span><span id="__span-45-14"><a id="__codelineno-45-14" name="__codelineno-45-14" href="#__codelineno-45-14"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">!</span><span class="nx">open</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-45-15"><a id="__codelineno-45-15" name="__codelineno-45-15" href="#__codelineno-45-15"></a><span class="hll"><span class="w"> </span><span class="nx">ch2</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="c1">// Assigns ch2 to a nil channel once closed</span>
</span></span><span id="__span-45-16"><a id="__codelineno-45-16" name="__codelineno-45-16" href="#__codelineno-45-16"></a><span class="w"> </span><span class="k">break</span>
</span><span id="__span-45-17"><a id="__codelineno-45-17" name="__codelineno-45-17" href="#__codelineno-45-17"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-45-18"><a id="__codelineno-45-18" name="__codelineno-45-18" href="#__codelineno-45-18"></a><span class="w"> </span><span class="nx">ch</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="nx">v</span>
</span><span id="__span-45-19"><a id="__codelineno-45-19" name="__codelineno-45-19" href="#__codelineno-45-19"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-45-20"><a id="__codelineno-45-20" name="__codelineno-45-20" href="#__codelineno-45-20"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-45-21"><a id="__codelineno-45-21" name="__codelineno-45-21" href="#__codelineno-45-21"></a><span class="w"> </span><span class="nb">close</span><span class="p">(</span><span class="nx">ch</span><span class="p">)</span>
</span><span id="__span-45-22"><a id="__codelineno-45-22" name="__codelineno-45-22" href="#__codelineno-45-22"></a><span class="w"> </span><span class="p">}()</span>
</span><span id="__span-45-23"><a id="__codelineno-45-23" name="__codelineno-45-23" href="#__codelineno-45-23"></a>
</span><span id="__span-45-24"><a id="__codelineno-45-24" name="__codelineno-45-24" href="#__codelineno-45-24"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">ch</span>
</span><span id="__span-45-25"><a id="__codelineno-45-25" name="__codelineno-45-25" href="#__codelineno-45-25"></a><span class="p">}</span>
</span></code></pre></div>
<p>This elegant solution relies on nil channels to somehow <em>remove</em> one case from the <code>select</code> statement.</p>
<p>Lets keep this idea in mind: nil channels are useful in some conditions and should be part of the Go developers toolset when dealing with concurrent code.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/66-nil-channels/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="ficar-intrigado-com-o-tamanho-do-canal-67">Ficar intrigado com o tamanho do canal (#67)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Decida cuidadosamente o tipo de canal correto a ser usado, considerando o problema. Somente canais sem buffer oferecem fortes garantias de sincronização. Para canais em buffer, você deve ter um bom motivo para especificar um tamanho de canal diferente de um.</p>
</details>
<p>An unbuffered channel is a channel without any capacity. It can be created by either omitting the size or providing a 0 size:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-46-1"><a id="__codelineno-46-1" name="__codelineno-46-1" href="#__codelineno-46-1"></a><span class="nx">ch1</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nb">make</span><span class="p">(</span><span class="kd">chan</span><span class="w"> </span><span class="kt">int</span><span class="p">)</span>
</span><span id="__span-46-2"><a id="__codelineno-46-2" name="__codelineno-46-2" href="#__codelineno-46-2"></a><span class="nx">ch2</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nb">make</span><span class="p">(</span><span class="kd">chan</span><span class="w"> </span><span class="kt">int</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
</span></code></pre></div>
<p>With an unbuffered channel (sometimes called a synchronous channel), the sender will block until the receiver receives data from the channel.</p>
<p>Conversely, a buffered channel has a capacity, and it must be created with a size greater than or equal to 1:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-47-1"><a id="__codelineno-47-1" name="__codelineno-47-1" href="#__codelineno-47-1"></a><span class="nx">ch3</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nb">make</span><span class="p">(</span><span class="kd">chan</span><span class="w"> </span><span class="kt">int</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span>
</span></code></pre></div>
<p>With a buffered channel, a sender can send messages while the channel isnt full. Once the channel is full, it will block until a receiver goroutine receives a message:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-48-1"><a id="__codelineno-48-1" name="__codelineno-48-1" href="#__codelineno-48-1"></a><span class="nx">ch3</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nb">make</span><span class="p">(</span><span class="kd">chan</span><span class="w"> </span><span class="kt">int</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span>
</span><span id="__span-48-2"><a id="__codelineno-48-2" name="__codelineno-48-2" href="#__codelineno-48-2"></a><span class="nx">ch3</span><span class="w"> </span><span class="o">&lt;-</span><span class="mi">1</span><span class="w"> </span><span class="c1">// Non-blocking</span>
</span><span id="__span-48-3"><a id="__codelineno-48-3" name="__codelineno-48-3" href="#__codelineno-48-3"></a><span class="nx">ch3</span><span class="w"> </span><span class="o">&lt;-</span><span class="mi">2</span><span class="w"> </span><span class="c1">// Blocking</span>
</span></code></pre></div>
<p>The first send isnt blocking, whereas the second one is, as the channel is full at this stage.</p>
<p>What's the main difference between unbuffered and buffered channels:</p>
<ul>
<li>An unbuffered channel enables synchronization. We have the guarantee that two goroutines will be in a known state: one receiving and another sending a message.</li>
<li>A buffered channel doesnt provide any strong synchronization. Indeed, a producer goroutine can send a message and then continue its execution if the channel isnt full. The only guarantee is that a goroutine wont receive a message before it is sent. But this is only a guarantee because of causality (you dont drink your coffee before you prepare it).</li>
</ul>
<p>If we need a buffered channel, what size should we provide?</p>
<p>The default value we should use for buffered channels is its minimum: 1. So, we may approach the problem from this standpoint: is there any good reason not to use a value of 1? Heres a list of possible cases where we should use another size:</p>
<ul>
<li>While using a worker pooling-like pattern, meaning spinning a fixed number of goroutines that need to send data to a shared channel. In that case, we can tie the channel size to the number of goroutines created.</li>
<li>When using channels for rate-limiting problems. For example, if we need to enforce resource utilization by bounding the number of requests, we should set up the channel size according to the limit.</li>
</ul>
<p>If we are outside of these cases, using a different channel size should be done cautiously. Lets bear in mind that deciding about an accurate queue size isnt an easy problem:</p>
<div class="admonition quote">
<p class="admonition-title">Martin Thompson</p>
<p>Queues are typically always close to full or close to empty due to the differences in pace between consumers and producers. They very rarely operate in a balanced middle ground where the rate of production and consumption is evenly matched.</p>
</div>
<h3 id="esquecendo-os-possiveis-efeitos-colaterais-da-formatacao-de-strings-68">Esquecendo os possíveis efeitos colaterais da formatação de strings (#68)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Estar ciente de que a formatação de strings pode levar à chamada de funções existentes significa estar atento a possíveis impasses e outras disputas de dados.</p>
</details>
<p>Its pretty easy to forget the potential side effects of string formatting while working in a concurrent application.</p>
<h4 id="etcd-data-race"><a href="https://github.com/etcd-io/etcd">etcd</a> data race</h4>
<p><a href="https://github.com/etcd-io/etcd/pull/7816">github.com/etcd-io/etcd/pull/7816</a> shows an example of an issue where a map's key was formatted based on a mutable values from a context.</p>
<h4 id="deadlock">Deadlock</h4>
<p>Can you see what the problem is in this code with a <code>Customer</code> struct exposing an <code>UpdateAge</code> method and implementing the <code>fmt.Stringer</code> interface?</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-49-1"><a id="__codelineno-49-1" name="__codelineno-49-1" href="#__codelineno-49-1"></a><span class="kd">type</span><span class="w"> </span><span class="nx">Customer</span><span class="w"> </span><span class="kd">struct</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-49-2"><a id="__codelineno-49-2" name="__codelineno-49-2" href="#__codelineno-49-2"></a><span class="w"> </span><span class="nx">mutex</span><span class="w"> </span><span class="nx">sync</span><span class="p">.</span><span class="nx">RWMutex</span><span class="w"> </span><span class="c1">// Uses a sync.RWMutex to protect concurrent accesses</span>
</span><span id="__span-49-3"><a id="__codelineno-49-3" name="__codelineno-49-3" href="#__codelineno-49-3"></a><span class="w"> </span><span class="nx">id</span><span class="w"> </span><span class="kt">string</span>
</span><span id="__span-49-4"><a id="__codelineno-49-4" name="__codelineno-49-4" href="#__codelineno-49-4"></a><span class="w"> </span><span class="nx">age</span><span class="w"> </span><span class="kt">int</span>
</span><span id="__span-49-5"><a id="__codelineno-49-5" name="__codelineno-49-5" href="#__codelineno-49-5"></a><span class="p">}</span>
</span><span id="__span-49-6"><a id="__codelineno-49-6" name="__codelineno-49-6" href="#__codelineno-49-6"></a>
</span><span id="__span-49-7"><a id="__codelineno-49-7" name="__codelineno-49-7" href="#__codelineno-49-7"></a><span class="kd">func</span><span class="w"> </span><span class="p">(</span><span class="nx">c</span><span class="w"> </span><span class="o">*</span><span class="nx">Customer</span><span class="p">)</span><span class="w"> </span><span class="nx">UpdateAge</span><span class="p">(</span><span class="nx">age</span><span class="w"> </span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="kt">error</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-49-8"><a id="__codelineno-49-8" name="__codelineno-49-8" href="#__codelineno-49-8"></a><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">mutex</span><span class="p">.</span><span class="nx">Lock</span><span class="p">()</span><span class="w"> </span><span class="c1">// Locks and defers unlock as we update Customer</span>
</span><span id="__span-49-9"><a id="__codelineno-49-9" name="__codelineno-49-9" href="#__codelineno-49-9"></a><span class="w"> </span><span class="k">defer</span><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">mutex</span><span class="p">.</span><span class="nx">Unlock</span><span class="p">()</span>
</span><span id="__span-49-10"><a id="__codelineno-49-10" name="__codelineno-49-10" href="#__codelineno-49-10"></a>
</span><span id="__span-49-11"><a id="__codelineno-49-11" name="__codelineno-49-11" href="#__codelineno-49-11"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">age</span><span class="w"> </span><span class="p">&lt;</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="c1">// Returns an error if age is negative</span>
</span><span id="__span-49-12"><a id="__codelineno-49-12" name="__codelineno-49-12" href="#__codelineno-49-12"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Errorf</span><span class="p">(</span><span class="s">&quot;age should be positive for customer %v&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">c</span><span class="p">)</span>
</span><span id="__span-49-13"><a id="__codelineno-49-13" name="__codelineno-49-13" href="#__codelineno-49-13"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-49-14"><a id="__codelineno-49-14" name="__codelineno-49-14" href="#__codelineno-49-14"></a>
</span><span id="__span-49-15"><a id="__codelineno-49-15" name="__codelineno-49-15" href="#__codelineno-49-15"></a><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">age</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">age</span>
</span><span id="__span-49-16"><a id="__codelineno-49-16" name="__codelineno-49-16" href="#__codelineno-49-16"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="kc">nil</span>
</span><span id="__span-49-17"><a id="__codelineno-49-17" name="__codelineno-49-17" href="#__codelineno-49-17"></a><span class="p">}</span>
</span><span id="__span-49-18"><a id="__codelineno-49-18" name="__codelineno-49-18" href="#__codelineno-49-18"></a>
</span><span id="__span-49-19"><a id="__codelineno-49-19" name="__codelineno-49-19" href="#__codelineno-49-19"></a><span class="kd">func</span><span class="w"> </span><span class="p">(</span><span class="nx">c</span><span class="w"> </span><span class="o">*</span><span class="nx">Customer</span><span class="p">)</span><span class="w"> </span><span class="nx">String</span><span class="p">()</span><span class="w"> </span><span class="kt">string</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-49-20"><a id="__codelineno-49-20" name="__codelineno-49-20" href="#__codelineno-49-20"></a><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">mutex</span><span class="p">.</span><span class="nx">RLock</span><span class="p">()</span><span class="w"> </span><span class="c1">// Locks and defers unlock as we read Customer</span>
</span><span id="__span-49-21"><a id="__codelineno-49-21" name="__codelineno-49-21" href="#__codelineno-49-21"></a><span class="w"> </span><span class="k">defer</span><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">mutex</span><span class="p">.</span><span class="nx">RUnlock</span><span class="p">()</span>
</span><span id="__span-49-22"><a id="__codelineno-49-22" name="__codelineno-49-22" href="#__codelineno-49-22"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Sprintf</span><span class="p">(</span><span class="s">&quot;id %s, age %d&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">id</span><span class="p">,</span><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">age</span><span class="p">)</span>
</span><span id="__span-49-23"><a id="__codelineno-49-23" name="__codelineno-49-23" href="#__codelineno-49-23"></a><span class="p">}</span>
</span></code></pre></div>
<p>The problem here may not be straightforward. If the provided age is negative, we return an error. Because the error is formatted, using the <code>%s</code> directive on the receiver, it will call the <code>String</code> method to format <code>Customer</code>. But because <code>UpdateAge</code> already acquires the mutex lock, the <code>String</code> method wont be able to acquire it. Hence, this leads to a deadlock situation. If all goroutines are also asleep, it leads to a panic.</p>
<p>One possible solution is to restrict the scope of the mutex lock:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-50-1"><a id="__codelineno-50-1" name="__codelineno-50-1" href="#__codelineno-50-1"></a><span class="kd">func</span><span class="w"> </span><span class="p">(</span><span class="nx">c</span><span class="w"> </span><span class="o">*</span><span class="nx">Customer</span><span class="p">)</span><span class="w"> </span><span class="nx">UpdateAge</span><span class="p">(</span><span class="nx">age</span><span class="w"> </span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="kt">error</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-50-2"><a id="__codelineno-50-2" name="__codelineno-50-2" href="#__codelineno-50-2"></a><span class="hll"><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">age</span><span class="w"> </span><span class="p">&lt;</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span>
</span></span><span id="__span-50-3"><a id="__codelineno-50-3" name="__codelineno-50-3" href="#__codelineno-50-3"></a><span class="hll"><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Errorf</span><span class="p">(</span><span class="s">&quot;age should be positive for customer %v&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">c</span><span class="p">)</span>
</span></span><span id="__span-50-4"><a id="__codelineno-50-4" name="__codelineno-50-4" href="#__codelineno-50-4"></a><span class="hll"><span class="w"> </span><span class="p">}</span>
</span></span><span id="__span-50-5"><a id="__codelineno-50-5" name="__codelineno-50-5" href="#__codelineno-50-5"></a>
</span><span id="__span-50-6"><a id="__codelineno-50-6" name="__codelineno-50-6" href="#__codelineno-50-6"></a><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">mutex</span><span class="p">.</span><span class="nx">Lock</span><span class="p">()</span><span class="w"> </span><span class="p">&lt;</span><span class="mi">1</span><span class="p">&gt;</span>
</span><span id="__span-50-7"><a id="__codelineno-50-7" name="__codelineno-50-7" href="#__codelineno-50-7"></a><span class="w"> </span><span class="k">defer</span><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">mutex</span><span class="p">.</span><span class="nx">Unlock</span><span class="p">()</span>
</span><span id="__span-50-8"><a id="__codelineno-50-8" name="__codelineno-50-8" href="#__codelineno-50-8"></a>
</span><span id="__span-50-9"><a id="__codelineno-50-9" name="__codelineno-50-9" href="#__codelineno-50-9"></a><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">age</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">age</span>
</span><span id="__span-50-10"><a id="__codelineno-50-10" name="__codelineno-50-10" href="#__codelineno-50-10"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="kc">nil</span>
</span><span id="__span-50-11"><a id="__codelineno-50-11" name="__codelineno-50-11" href="#__codelineno-50-11"></a><span class="p">}</span>
</span></code></pre></div>
<p>Yet, such an approach isn't always possible. In these conditions, we have to be extremely careful with string formatting.</p>
<p>Another approach is to access the <code>id</code> field directly:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-51-1"><a id="__codelineno-51-1" name="__codelineno-51-1" href="#__codelineno-51-1"></a><span class="kd">func</span><span class="w"> </span><span class="p">(</span><span class="nx">c</span><span class="w"> </span><span class="o">*</span><span class="nx">Customer</span><span class="p">)</span><span class="w"> </span><span class="nx">UpdateAge</span><span class="p">(</span><span class="nx">age</span><span class="w"> </span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="kt">error</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-51-2"><a id="__codelineno-51-2" name="__codelineno-51-2" href="#__codelineno-51-2"></a><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">mutex</span><span class="p">.</span><span class="nx">Lock</span><span class="p">()</span>
</span><span id="__span-51-3"><a id="__codelineno-51-3" name="__codelineno-51-3" href="#__codelineno-51-3"></a><span class="w"> </span><span class="k">defer</span><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">mutex</span><span class="p">.</span><span class="nx">Unlock</span><span class="p">()</span>
</span><span id="__span-51-4"><a id="__codelineno-51-4" name="__codelineno-51-4" href="#__codelineno-51-4"></a>
</span><span id="__span-51-5"><a id="__codelineno-51-5" name="__codelineno-51-5" href="#__codelineno-51-5"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">age</span><span class="w"> </span><span class="p">&lt;</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-51-6"><a id="__codelineno-51-6" name="__codelineno-51-6" href="#__codelineno-51-6"></a><span class="hll"><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Errorf</span><span class="p">(</span><span class="s">&quot;age should be positive for customer id %s&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">id</span><span class="p">)</span>
</span></span><span id="__span-51-7"><a id="__codelineno-51-7" name="__codelineno-51-7" href="#__codelineno-51-7"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-51-8"><a id="__codelineno-51-8" name="__codelineno-51-8" href="#__codelineno-51-8"></a>
</span><span id="__span-51-9"><a id="__codelineno-51-9" name="__codelineno-51-9" href="#__codelineno-51-9"></a><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">age</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">age</span>
</span><span id="__span-51-10"><a id="__codelineno-51-10" name="__codelineno-51-10" href="#__codelineno-51-10"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="kc">nil</span>
</span><span id="__span-51-11"><a id="__codelineno-51-11" name="__codelineno-51-11" href="#__codelineno-51-11"></a><span class="p">}</span>
</span></code></pre></div>
<p>In concurrent applications, we should remain cautious about the possible side effects of string formatting.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/68-string-formatting/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="criando-corridas-de-dados-com-acrescimo-69">Criando corridas de dados com acréscimo (#69)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>As chamadas <code>append</code> nem sempre são isentas de disputa de dados; portanto, não deve ser usado simultaneamente em uma slice compartilhada.</p>
</details>
<p>Should adding an element to a slice using <code>append</code> is data-race-free? Spoiler: it depends.</p>
<p>Do you believe this example has a data race? </p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-52-1"><a id="__codelineno-52-1" name="__codelineno-52-1" href="#__codelineno-52-1"></a><span class="nx">s</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nb">make</span><span class="p">([]</span><span class="kt">int</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span>
</span><span id="__span-52-2"><a id="__codelineno-52-2" name="__codelineno-52-2" href="#__codelineno-52-2"></a>
</span><span id="__span-52-3"><a id="__codelineno-52-3" name="__codelineno-52-3" href="#__codelineno-52-3"></a><span class="k">go</span><span class="w"> </span><span class="kd">func</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="c1">// In a new goroutine, appends a new element on s</span>
</span><span id="__span-52-4"><a id="__codelineno-52-4" name="__codelineno-52-4" href="#__codelineno-52-4"></a><span class="w"> </span><span class="nx">s1</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nb">append</span><span class="p">(</span><span class="nx">s</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span>
</span><span id="__span-52-5"><a id="__codelineno-52-5" name="__codelineno-52-5" href="#__codelineno-52-5"></a><span class="w"> </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="nx">s1</span><span class="p">)</span>
</span><span id="__span-52-6"><a id="__codelineno-52-6" name="__codelineno-52-6" href="#__codelineno-52-6"></a><span class="p">}()</span>
</span><span id="__span-52-7"><a id="__codelineno-52-7" name="__codelineno-52-7" href="#__codelineno-52-7"></a>
</span><span id="__span-52-8"><a id="__codelineno-52-8" name="__codelineno-52-8" href="#__codelineno-52-8"></a><span class="k">go</span><span class="w"> </span><span class="kd">func</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="c1">// Same</span>
</span><span id="__span-52-9"><a id="__codelineno-52-9" name="__codelineno-52-9" href="#__codelineno-52-9"></a><span class="w"> </span><span class="nx">s2</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nb">append</span><span class="p">(</span><span class="nx">s</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span>
</span><span id="__span-52-10"><a id="__codelineno-52-10" name="__codelineno-52-10" href="#__codelineno-52-10"></a><span class="w"> </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="nx">s2</span><span class="p">)</span>
</span><span id="__span-52-11"><a id="__codelineno-52-11" name="__codelineno-52-11" href="#__codelineno-52-11"></a><span class="p">}()</span>
</span></code></pre></div>
<p>The answer is no.</p>
<p>In this example, we create a slice with <code>make([]int, 1)</code>. The code creates a one-length, one-capacity slice. Thus, because the slice is full, using append in each goroutine returns a slice backed by a new array. It doesnt mutate the existing array; hence, it doesnt lead to a data race.</p>
<p>Now, lets run the same example with a slight change in how we initialize <code>s</code>. Instead of creating a slice with a length of 1, we create it with a length of 0 but a capacity of 1. How about this new example? Does it contain a data race?</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-53-1"><a id="__codelineno-53-1" name="__codelineno-53-1" href="#__codelineno-53-1"></a><span class="hll"><span class="nx">s</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nb">make</span><span class="p">([]</span><span class="kt">int</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span>
</span></span><span id="__span-53-2"><a id="__codelineno-53-2" name="__codelineno-53-2" href="#__codelineno-53-2"></a>
</span><span id="__span-53-3"><a id="__codelineno-53-3" name="__codelineno-53-3" href="#__codelineno-53-3"></a><span class="k">go</span><span class="w"> </span><span class="kd">func</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span>
</span><span id="__span-53-4"><a id="__codelineno-53-4" name="__codelineno-53-4" href="#__codelineno-53-4"></a><span class="w"> </span><span class="nx">s1</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nb">append</span><span class="p">(</span><span class="nx">s</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span>
</span><span id="__span-53-5"><a id="__codelineno-53-5" name="__codelineno-53-5" href="#__codelineno-53-5"></a><span class="w"> </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="nx">s1</span><span class="p">)</span>
</span><span id="__span-53-6"><a id="__codelineno-53-6" name="__codelineno-53-6" href="#__codelineno-53-6"></a><span class="p">}()</span>
</span><span id="__span-53-7"><a id="__codelineno-53-7" name="__codelineno-53-7" href="#__codelineno-53-7"></a>
</span><span id="__span-53-8"><a id="__codelineno-53-8" name="__codelineno-53-8" href="#__codelineno-53-8"></a><span class="k">go</span><span class="w"> </span><span class="kd">func</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-53-9"><a id="__codelineno-53-9" name="__codelineno-53-9" href="#__codelineno-53-9"></a><span class="w"> </span><span class="nx">s2</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nb">append</span><span class="p">(</span><span class="nx">s</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span>
</span><span id="__span-53-10"><a id="__codelineno-53-10" name="__codelineno-53-10" href="#__codelineno-53-10"></a><span class="w"> </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="nx">s2</span><span class="p">)</span>
</span><span id="__span-53-11"><a id="__codelineno-53-11" name="__codelineno-53-11" href="#__codelineno-53-11"></a><span class="p">}()</span>
</span></code></pre></div>
<p>The answer is yes. We create a slice with <code>make([]int, 0, 1)</code>. Therefore, the array isnt full. Both goroutines attempt to update the same index of the backing array (index 1), which is a data race.</p>
<p>How can we prevent the data race if we want both goroutines to work on a slice containing the initial elements of <code>s</code> plus an extra element? One solution is to create a copy of <code>s</code>.</p>
<p>We should remember that using append on a shared slice in concurrent applications can lead to a data race. Hence, it should be avoided.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/69-data-race-append/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="usando-mutexes-imprecisamente-com-slices-e-maps-70">Usando mutexes imprecisamente com slices e maps (#70)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Lembrar que slices e maps são ponteiros pode evitar corridas comuns de dados.</p>
</details>
<p>Let's implement a <code>Cache</code> struct used to handle caching for customer balances. This struct will contain a map of balances per customer ID and a mutex to protect concurrent accesses:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-54-1"><a id="__codelineno-54-1" name="__codelineno-54-1" href="#__codelineno-54-1"></a><span class="kd">type</span><span class="w"> </span><span class="nx">Cache</span><span class="w"> </span><span class="kd">struct</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-54-2"><a id="__codelineno-54-2" name="__codelineno-54-2" href="#__codelineno-54-2"></a><span class="w"> </span><span class="nx">mu</span><span class="w"> </span><span class="nx">sync</span><span class="p">.</span><span class="nx">RWMutex</span>
</span><span id="__span-54-3"><a id="__codelineno-54-3" name="__codelineno-54-3" href="#__codelineno-54-3"></a><span class="w"> </span><span class="nx">balances</span><span class="w"> </span><span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="kt">float64</span>
</span><span id="__span-54-4"><a id="__codelineno-54-4" name="__codelineno-54-4" href="#__codelineno-54-4"></a><span class="p">}</span>
</span></code></pre></div>
<p>Next, we add an <code>AddBalance</code> method that mutates the <code>balances</code> map. The mutation is done in a critical section (within a mutex lock and a mutex unlock):</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-55-1"><a id="__codelineno-55-1" name="__codelineno-55-1" href="#__codelineno-55-1"></a><span class="kd">func</span><span class="w"> </span><span class="p">(</span><span class="nx">c</span><span class="w"> </span><span class="o">*</span><span class="nx">Cache</span><span class="p">)</span><span class="w"> </span><span class="nx">AddBalance</span><span class="p">(</span><span class="nx">id</span><span class="w"> </span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="nx">balance</span><span class="w"> </span><span class="kt">float64</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-55-2"><a id="__codelineno-55-2" name="__codelineno-55-2" href="#__codelineno-55-2"></a><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">mu</span><span class="p">.</span><span class="nx">Lock</span><span class="p">()</span>
</span><span id="__span-55-3"><a id="__codelineno-55-3" name="__codelineno-55-3" href="#__codelineno-55-3"></a><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">balances</span><span class="p">[</span><span class="nx">id</span><span class="p">]</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">balance</span>
</span><span id="__span-55-4"><a id="__codelineno-55-4" name="__codelineno-55-4" href="#__codelineno-55-4"></a><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">mu</span><span class="p">.</span><span class="nx">Unlock</span><span class="p">()</span>
</span><span id="__span-55-5"><a id="__codelineno-55-5" name="__codelineno-55-5" href="#__codelineno-55-5"></a><span class="p">}</span>
</span></code></pre></div>
<p>Meanwhile, we have to implement a method to calculate the average balance for all the customers. One idea is to handle a minimal critical section this way:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-56-1"><a id="__codelineno-56-1" name="__codelineno-56-1" href="#__codelineno-56-1"></a><span class="kd">func</span><span class="w"> </span><span class="p">(</span><span class="nx">c</span><span class="w"> </span><span class="o">*</span><span class="nx">Cache</span><span class="p">)</span><span class="w"> </span><span class="nx">AverageBalance</span><span class="p">()</span><span class="w"> </span><span class="kt">float64</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-56-2"><a id="__codelineno-56-2" name="__codelineno-56-2" href="#__codelineno-56-2"></a><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">mu</span><span class="p">.</span><span class="nx">RLock</span><span class="p">()</span>
</span><span id="__span-56-3"><a id="__codelineno-56-3" name="__codelineno-56-3" href="#__codelineno-56-3"></a><span class="w"> </span><span class="nx">balances</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">balances</span><span class="w"> </span><span class="c1">// Creates a copy of the balances map</span>
</span><span id="__span-56-4"><a id="__codelineno-56-4" name="__codelineno-56-4" href="#__codelineno-56-4"></a><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">mu</span><span class="p">.</span><span class="nx">RUnlock</span><span class="p">()</span>
</span><span id="__span-56-5"><a id="__codelineno-56-5" name="__codelineno-56-5" href="#__codelineno-56-5"></a>
</span><span id="__span-56-6"><a id="__codelineno-56-6" name="__codelineno-56-6" href="#__codelineno-56-6"></a><span class="w"> </span><span class="nx">sum</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="mf">0.</span>
</span><span id="__span-56-7"><a id="__codelineno-56-7" name="__codelineno-56-7" href="#__codelineno-56-7"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">balance</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">balances</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="c1">// Iterates over the copy, outside of the critical section</span>
</span><span id="__span-56-8"><a id="__codelineno-56-8" name="__codelineno-56-8" href="#__codelineno-56-8"></a><span class="w"> </span><span class="nx">sum</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="nx">balance</span>
</span><span id="__span-56-9"><a id="__codelineno-56-9" name="__codelineno-56-9" href="#__codelineno-56-9"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-56-10"><a id="__codelineno-56-10" name="__codelineno-56-10" href="#__codelineno-56-10"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">sum</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nb">float64</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="nx">balances</span><span class="p">))</span>
</span><span id="__span-56-11"><a id="__codelineno-56-11" name="__codelineno-56-11" href="#__codelineno-56-11"></a><span class="p">}</span>
</span></code></pre></div>
<p>What's the problem with this code?</p>
<p>If we run a test using the <code>-race</code> flag with two concurrent goroutines, one calling <code>AddBalance</code> (hence mutating balances) and another calling <code>AverageBalance</code>, a data race occurs. Whats the problem here?</p>
<p>Internally, a map is a <code>runtime.hmap</code> struct containing mostly metadata (for example, a counter) and a pointer referencing data buckets. So, <code>balances := c.balances</code> doesnt copy the actual data. Therefore, the two goroutines perform operations on the same data set, and one mutates it. Hence, it's a data race.</p>
<p>One possible solution is to protect the whole <code>AverageBalance</code> function:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-57-1"><a id="__codelineno-57-1" name="__codelineno-57-1" href="#__codelineno-57-1"></a><span class="kd">func</span><span class="w"> </span><span class="p">(</span><span class="nx">c</span><span class="w"> </span><span class="o">*</span><span class="nx">Cache</span><span class="p">)</span><span class="w"> </span><span class="nx">AverageBalance</span><span class="p">()</span><span class="w"> </span><span class="kt">float64</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-57-2"><a id="__codelineno-57-2" name="__codelineno-57-2" href="#__codelineno-57-2"></a><span class="hll"><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">mu</span><span class="p">.</span><span class="nx">RLock</span><span class="p">()</span>
</span></span><span id="__span-57-3"><a id="__codelineno-57-3" name="__codelineno-57-3" href="#__codelineno-57-3"></a><span class="hll"><span class="w"> </span><span class="k">defer</span><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">mu</span><span class="p">.</span><span class="nx">RUnlock</span><span class="p">()</span><span class="w"> </span><span class="c1">// Unlocks when the function returns</span>
</span></span><span id="__span-57-4"><a id="__codelineno-57-4" name="__codelineno-57-4" href="#__codelineno-57-4"></a>
</span><span id="__span-57-5"><a id="__codelineno-57-5" name="__codelineno-57-5" href="#__codelineno-57-5"></a><span class="w"> </span><span class="nx">sum</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="mf">0.</span>
</span><span id="__span-57-6"><a id="__codelineno-57-6" name="__codelineno-57-6" href="#__codelineno-57-6"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">balance</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">balances</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-57-7"><a id="__codelineno-57-7" name="__codelineno-57-7" href="#__codelineno-57-7"></a><span class="w"> </span><span class="nx">sum</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="nx">balance</span>
</span><span id="__span-57-8"><a id="__codelineno-57-8" name="__codelineno-57-8" href="#__codelineno-57-8"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-57-9"><a id="__codelineno-57-9" name="__codelineno-57-9" href="#__codelineno-57-9"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">sum</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nb">float64</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">balances</span><span class="p">))</span>
</span><span id="__span-57-10"><a id="__codelineno-57-10" name="__codelineno-57-10" href="#__codelineno-57-10"></a><span class="p">}</span>
</span></code></pre></div>
<p>Another option, if the iteration operation isnt lightweight, is to work on an actual copy of the data and protect only the copy:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-58-1"><a id="__codelineno-58-1" name="__codelineno-58-1" href="#__codelineno-58-1"></a><span class="kd">func</span><span class="w"> </span><span class="p">(</span><span class="nx">c</span><span class="w"> </span><span class="o">*</span><span class="nx">Cache</span><span class="p">)</span><span class="w"> </span><span class="nx">AverageBalance</span><span class="p">()</span><span class="w"> </span><span class="kt">float64</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-58-2"><a id="__codelineno-58-2" name="__codelineno-58-2" href="#__codelineno-58-2"></a><span class="hll"><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">mu</span><span class="p">.</span><span class="nx">RLock</span><span class="p">()</span>
</span></span><span id="__span-58-3"><a id="__codelineno-58-3" name="__codelineno-58-3" href="#__codelineno-58-3"></a><span class="hll"><span class="w"> </span><span class="nx">m</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nb">make</span><span class="p">(</span><span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="kt">float64</span><span class="p">,</span><span class="w"> </span><span class="nb">len</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">balances</span><span class="p">))</span><span class="w"> </span><span class="c1">// Copies the map</span>
</span></span><span id="__span-58-4"><a id="__codelineno-58-4" name="__codelineno-58-4" href="#__codelineno-58-4"></a><span class="hll"><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="nx">k</span><span class="p">,</span><span class="w"> </span><span class="nx">v</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">balances</span><span class="w"> </span><span class="p">{</span>
</span></span><span id="__span-58-5"><a id="__codelineno-58-5" name="__codelineno-58-5" href="#__codelineno-58-5"></a><span class="hll"><span class="w"> </span><span class="nx">m</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">v</span>
</span></span><span id="__span-58-6"><a id="__codelineno-58-6" name="__codelineno-58-6" href="#__codelineno-58-6"></a><span class="hll"><span class="w"> </span><span class="p">}</span>
</span></span><span id="__span-58-7"><a id="__codelineno-58-7" name="__codelineno-58-7" href="#__codelineno-58-7"></a><span class="hll"><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">mu</span><span class="p">.</span><span class="nx">RUnlock</span><span class="p">()</span>
</span></span><span id="__span-58-8"><a id="__codelineno-58-8" name="__codelineno-58-8" href="#__codelineno-58-8"></a>
</span><span id="__span-58-9"><a id="__codelineno-58-9" name="__codelineno-58-9" href="#__codelineno-58-9"></a><span class="w"> </span><span class="nx">sum</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="mf">0.</span>
</span><span id="__span-58-10"><a id="__codelineno-58-10" name="__codelineno-58-10" href="#__codelineno-58-10"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">balance</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">m</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-58-11"><a id="__codelineno-58-11" name="__codelineno-58-11" href="#__codelineno-58-11"></a><span class="w"> </span><span class="nx">sum</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="nx">balance</span>
</span><span id="__span-58-12"><a id="__codelineno-58-12" name="__codelineno-58-12" href="#__codelineno-58-12"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-58-13"><a id="__codelineno-58-13" name="__codelineno-58-13" href="#__codelineno-58-13"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">sum</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nb">float64</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="nx">m</span><span class="p">))</span>
</span><span id="__span-58-14"><a id="__codelineno-58-14" name="__codelineno-58-14" href="#__codelineno-58-14"></a><span class="p">}</span>
</span></code></pre></div>
<p>Once we have made a deep copy, we release the mutex. The iterations are done on the copy outside of the critical section.</p>
<p>In summary, we have to be careful with the boundaries of a mutex lock. In this section, we have seen why assigning an existing map (or an existing slice) to a map isnt enough to protect against data races. The new variable, whether a map or a slice, is backed by the same data set. There are two leading solutions to prevent this: protect the whole function, or work on a copy of the actual data. In all cases, lets be cautious when designing critical sections and make sure the boundaries are accurately defined.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/70-mutex-slices-maps/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="uso-indevido-syncwaitgroup-71">Uso indevido <code>sync.WaitGroup</code> (#71)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Para usar com precisão <code>sync.WaitGroup</code>, chame o método <code>Add</code> antes de ativar goroutines.</p>
</details>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/71-wait-group/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="esquecendo-synccond-72">Esquecendo <code>sync.Cond</code> (#72)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Você pode enviar notificações repetidas para vários goroutines com <code>sync.Cond</code>.</p>
</details>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/72-cond/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="nao-usando-errgroup-73">Não usando <code>errgroup</code> (#73)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Você pode sincronizar um grupo de goroutines e lidar com erros e contextos com o pacote <code>errgroup</code>.</p>
</details>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/73-errgroup/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="copiando-um-tipo-sync-74">Copiando um tipo <code>sync</code> (#74)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Tipos <code>sync</code> não devem ser copiados.</p>
</details>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/74-copying-sync/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h2 id="standard-library">Standard Library</h2>
<h3 id="fornecendo-uma-duracao-de-tempo-errada-75">Fornecendo uma duração de tempo errada (#75)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Seja cauteloso com funções que aceitam um arquivo <code>time.Duration</code>. Mesmo que a passagem de um número inteiro seja permitida, tente usar a API time para evitar qualquer possível confusão.</p>
</details>
<p>Many common functions in the standard library accept a <code>time.Duration</code>, which is an alias for the <code>int64</code> type. However, one <code>time.Duration</code> unit represents one nanosecond, instead of one millisecond, as commonly seen in other programming languages. As a result, passing numeric types instead of using the <code>time.Duration</code> API can lead to unexpected behavior.</p>
<p>A developer with experience in other languages might assume that the following code creates a new <code>time.Ticker</code> that delivers ticks every second, given the value <code>1000</code>:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-59-1"><a id="__codelineno-59-1" name="__codelineno-59-1" href="#__codelineno-59-1"></a><span class="nx">ticker</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">time</span><span class="p">.</span><span class="nx">NewTicker</span><span class="p">(</span><span class="mi">1000</span><span class="p">)</span>
</span><span id="__span-59-2"><a id="__codelineno-59-2" name="__codelineno-59-2" href="#__codelineno-59-2"></a><span class="k">for</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-59-3"><a id="__codelineno-59-3" name="__codelineno-59-3" href="#__codelineno-59-3"></a><span class="w"> </span><span class="k">select</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-59-4"><a id="__codelineno-59-4" name="__codelineno-59-4" href="#__codelineno-59-4"></a><span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="o">&lt;-</span><span class="nx">ticker</span><span class="p">.</span><span class="nx">C</span><span class="p">:</span>
</span><span id="__span-59-5"><a id="__codelineno-59-5" name="__codelineno-59-5" href="#__codelineno-59-5"></a><span class="w"> </span><span class="c1">// Do something</span>
</span><span id="__span-59-6"><a id="__codelineno-59-6" name="__codelineno-59-6" href="#__codelineno-59-6"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-59-7"><a id="__codelineno-59-7" name="__codelineno-59-7" href="#__codelineno-59-7"></a><span class="p">}</span>
</span></code></pre></div>
<p>However, because 1,000 <code>time.Duration</code> units = 1,000 nanoseconds, ticks are delivered every 1,000 nanoseconds = 1 microsecond, not every second as assumed.</p>
<p>We should always use the <code>time.Duration</code> API to avoid confusion and unexpected behavior:
<div class="language-go highlight"><pre><span></span><code><span id="__span-60-1"><a id="__codelineno-60-1" name="__codelineno-60-1" href="#__codelineno-60-1"></a><span class="nx">ticker</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">time</span><span class="p">.</span><span class="nx">NewTicker</span><span class="p">(</span><span class="nx">time</span><span class="p">.</span><span class="nx">Microsecond</span><span class="p">)</span>
</span><span id="__span-60-2"><a id="__codelineno-60-2" name="__codelineno-60-2" href="#__codelineno-60-2"></a><span class="c1">// Or</span>
</span><span id="__span-60-3"><a id="__codelineno-60-3" name="__codelineno-60-3" href="#__codelineno-60-3"></a><span class="nx">ticker</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">time</span><span class="p">.</span><span class="nx">NewTicker</span><span class="p">(</span><span class="mi">1000</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">time</span><span class="p">.</span><span class="nx">Nanosecond</span><span class="p">)</span>
</span></code></pre></div></p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/75-wrong-time-duration/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="timeafter-e-vazamentos-de-memoria-76"><code>time.After</code> e vazamentos de memória (#76)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Evitar chamadas para funções <code>time.After</code> repetidas (como loops ou manipuladores HTTP) pode evitar pico de consumo de memória. Os recursos criados por <code>time.After</code> são liberados somente quando o cronômetro expira.</p>
</details>
<p>Developers often use <code>time.After</code> in loops or HTTP handlers repeatedly to implement the timing function. But it can lead to unintended peak memory consumption due to the delayed release of resources, just like the following code:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-61-1"><a id="__codelineno-61-1" name="__codelineno-61-1" href="#__codelineno-61-1"></a><span class="kd">func</span><span class="w"> </span><span class="nx">consumer</span><span class="p">(</span><span class="nx">ch</span><span class="w"> </span><span class="o">&lt;-</span><span class="kd">chan</span><span class="w"> </span><span class="nx">Event</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-61-2"><a id="__codelineno-61-2" name="__codelineno-61-2" href="#__codelineno-61-2"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-61-3"><a id="__codelineno-61-3" name="__codelineno-61-3" href="#__codelineno-61-3"></a><span class="w"> </span><span class="k">select</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-61-4"><a id="__codelineno-61-4" name="__codelineno-61-4" href="#__codelineno-61-4"></a><span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="nx">event</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="o">&lt;-</span><span class="nx">ch</span><span class="p">:</span>
</span><span id="__span-61-5"><a id="__codelineno-61-5" name="__codelineno-61-5" href="#__codelineno-61-5"></a><span class="w"> </span><span class="nx">handle</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span>
</span><span id="__span-61-6"><a id="__codelineno-61-6" name="__codelineno-61-6" href="#__codelineno-61-6"></a><span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="o">&lt;-</span><span class="nx">time</span><span class="p">.</span><span class="nx">After</span><span class="p">(</span><span class="nx">time</span><span class="p">.</span><span class="nx">Hour</span><span class="p">):</span>
</span><span id="__span-61-7"><a id="__codelineno-61-7" name="__codelineno-61-7" href="#__codelineno-61-7"></a><span class="w"> </span><span class="nx">log</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="s">&quot;warning: no messages received&quot;</span><span class="p">)</span>
</span><span id="__span-61-8"><a id="__codelineno-61-8" name="__codelineno-61-8" href="#__codelineno-61-8"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-61-9"><a id="__codelineno-61-9" name="__codelineno-61-9" href="#__codelineno-61-9"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-61-10"><a id="__codelineno-61-10" name="__codelineno-61-10" href="#__codelineno-61-10"></a><span class="p">}</span>
</span></code></pre></div>
<p>The source code of the function time.After is as follows:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-62-1"><a id="__codelineno-62-1" name="__codelineno-62-1" href="#__codelineno-62-1"></a><span class="kd">func</span><span class="w"> </span><span class="nx">After</span><span class="p">(</span><span class="nx">d</span><span class="w"> </span><span class="nx">Duration</span><span class="p">)</span><span class="w"> </span><span class="o">&lt;-</span><span class="kd">chan</span><span class="w"> </span><span class="nx">Time</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-62-2"><a id="__codelineno-62-2" name="__codelineno-62-2" href="#__codelineno-62-2"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">NewTimer</span><span class="p">(</span><span class="nx">d</span><span class="p">).</span><span class="nx">C</span>
</span><span id="__span-62-3"><a id="__codelineno-62-3" name="__codelineno-62-3" href="#__codelineno-62-3"></a><span class="p">}</span>
</span></code></pre></div>
<p>As we see, it returns receive-only channel.</p>
<p>When <code>time.After</code> is used in a loop or repeated context, a new channel is created in each iteration. If these channels are not properly closed or if their associated timers are not stopped, they can accumulate and consume memory. The resources associated with each timer and channel are only released when the timer expires or the channel is closed.</p>
<p>To avoid this happening, We can use context's timeout setting instead of <code>time.After</code>, like below:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-63-1"><a id="__codelineno-63-1" name="__codelineno-63-1" href="#__codelineno-63-1"></a><span class="kd">func</span><span class="w"> </span><span class="nx">consumer</span><span class="p">(</span><span class="nx">ch</span><span class="w"> </span><span class="o">&lt;-</span><span class="kd">chan</span><span class="w"> </span><span class="nx">Event</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-63-2"><a id="__codelineno-63-2" name="__codelineno-63-2" href="#__codelineno-63-2"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-63-3"><a id="__codelineno-63-3" name="__codelineno-63-3" href="#__codelineno-63-3"></a><span class="w"> </span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="nx">cancel</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">WithTimeout</span><span class="p">(</span><span class="nx">context</span><span class="p">.</span><span class="nx">Background</span><span class="p">(),</span><span class="w"> </span><span class="nx">time</span><span class="p">.</span><span class="nx">Hour</span><span class="p">)</span>
</span><span id="__span-63-4"><a id="__codelineno-63-4" name="__codelineno-63-4" href="#__codelineno-63-4"></a><span class="w"> </span><span class="k">select</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-63-5"><a id="__codelineno-63-5" name="__codelineno-63-5" href="#__codelineno-63-5"></a><span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="nx">event</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="o">&lt;-</span><span class="nx">ch</span><span class="p">:</span>
</span><span id="__span-63-6"><a id="__codelineno-63-6" name="__codelineno-63-6" href="#__codelineno-63-6"></a><span class="w"> </span><span class="nx">cancel</span><span class="p">()</span>
</span><span id="__span-63-7"><a id="__codelineno-63-7" name="__codelineno-63-7" href="#__codelineno-63-7"></a><span class="w"> </span><span class="nx">handle</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span>
</span><span id="__span-63-8"><a id="__codelineno-63-8" name="__codelineno-63-8" href="#__codelineno-63-8"></a><span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="o">&lt;-</span><span class="nx">ctx</span><span class="p">.</span><span class="nx">Done</span><span class="p">():</span>
</span><span id="__span-63-9"><a id="__codelineno-63-9" name="__codelineno-63-9" href="#__codelineno-63-9"></a><span class="w"> </span><span class="nx">log</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="s">&quot;warning: no messages received&quot;</span><span class="p">)</span>
</span><span id="__span-63-10"><a id="__codelineno-63-10" name="__codelineno-63-10" href="#__codelineno-63-10"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-63-11"><a id="__codelineno-63-11" name="__codelineno-63-11" href="#__codelineno-63-11"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-63-12"><a id="__codelineno-63-12" name="__codelineno-63-12" href="#__codelineno-63-12"></a><span class="p">}</span>
</span></code></pre></div>
<p>We can also use <code>time.NewTimer</code> like so:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-64-1"><a id="__codelineno-64-1" name="__codelineno-64-1" href="#__codelineno-64-1"></a><span class="kd">func</span><span class="w"> </span><span class="nx">consumer</span><span class="p">(</span><span class="nx">ch</span><span class="w"> </span><span class="o">&lt;-</span><span class="kd">chan</span><span class="w"> </span><span class="nx">Event</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-64-2"><a id="__codelineno-64-2" name="__codelineno-64-2" href="#__codelineno-64-2"></a><span class="w"> </span><span class="nx">timerDuration</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">time</span><span class="p">.</span><span class="nx">Hour</span>
</span><span id="__span-64-3"><a id="__codelineno-64-3" name="__codelineno-64-3" href="#__codelineno-64-3"></a><span class="w"> </span><span class="nx">timer</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">time</span><span class="p">.</span><span class="nx">NewTimer</span><span class="p">(</span><span class="nx">timerDuration</span><span class="p">)</span>
</span><span id="__span-64-4"><a id="__codelineno-64-4" name="__codelineno-64-4" href="#__codelineno-64-4"></a>
</span><span id="__span-64-5"><a id="__codelineno-64-5" name="__codelineno-64-5" href="#__codelineno-64-5"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-64-6"><a id="__codelineno-64-6" name="__codelineno-64-6" href="#__codelineno-64-6"></a><span class="w"> </span><span class="nx">timer</span><span class="p">.</span><span class="nx">Reset</span><span class="p">(</span><span class="nx">timerDuration</span><span class="p">)</span>
</span><span id="__span-64-7"><a id="__codelineno-64-7" name="__codelineno-64-7" href="#__codelineno-64-7"></a><span class="w"> </span><span class="k">select</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-64-8"><a id="__codelineno-64-8" name="__codelineno-64-8" href="#__codelineno-64-8"></a><span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="nx">event</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="o">&lt;-</span><span class="nx">ch</span><span class="p">:</span>
</span><span id="__span-64-9"><a id="__codelineno-64-9" name="__codelineno-64-9" href="#__codelineno-64-9"></a><span class="w"> </span><span class="nx">handle</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span>
</span><span id="__span-64-10"><a id="__codelineno-64-10" name="__codelineno-64-10" href="#__codelineno-64-10"></a><span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="o">&lt;-</span><span class="nx">timer</span><span class="p">.</span><span class="nx">C</span><span class="p">:</span>
</span><span id="__span-64-11"><a id="__codelineno-64-11" name="__codelineno-64-11" href="#__codelineno-64-11"></a><span class="w"> </span><span class="nx">log</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="s">&quot;warning: no messages received&quot;</span><span class="p">)</span>
</span><span id="__span-64-12"><a id="__codelineno-64-12" name="__codelineno-64-12" href="#__codelineno-64-12"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-64-13"><a id="__codelineno-64-13" name="__codelineno-64-13" href="#__codelineno-64-13"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-64-14"><a id="__codelineno-64-14" name="__codelineno-64-14" href="#__codelineno-64-14"></a><span class="p">}</span>
</span></code></pre></div>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/76-time-after/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="lidando-com-erros-comuns-json-77">Lidando com erros comuns JSON (#77)</h3>
<ul>
<li>Comportamento inesperado devido à incorporação de tipo</li>
</ul>
<p>Tenha cuidado ao usar campos incorporados em estruturas Go. Fazer isso pode levar a bugs sorrateiros, como um campo time.Time incorporado que implementa a interface <code>json.Marshaler</code>, substituindo assim o comportamento de empacotamento padrão.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/77-json-handling/type-embedding/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<ul>
<li>JSON e o relógio monotônico</li>
</ul>
<p>Ao comparar duas estruturas <code>time.Time</code>, lembre-se de que <code>time.Time</code> contém um relógio de parede e um relógio monotônico, e a comparação usando o operador == é feita em ambos os relógios.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/77-json-handling/monotonic-clock/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<ul>
<li>Map de <code>any</code></li>
</ul>
<p>Para evitar suposições erradas ao fornecer um map ao desempacotar (unmarshaling) dados JSON, lembre-se de que os valores numéricos são convertidos para <code>float64</code> por padrão.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/77-json-handling/map-any/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="erros-comuns-de-sql-78">Erros comuns de SQL (#78)</h3>
<ul>
<li>Esquecer <code>sql.Open</code> não necessariamente estabelece conexões com um banco de dados</li>
</ul>
<p>Esquecer <code>sql.Open</code> não necessariamente estabelece conexões com um banco de dados
Chame o método <code>Ping</code> ou <code>PingContext</code> se precisar testar sua configuração e garantir que um banco de dados esteja acessível.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/78-sql/sql-open"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<ul>
<li>Esquecendo o pool de conexões</li>
</ul>
<p>Configure os parâmetros de conexão do banco de dados para aplicativos de nível de produção.</p>
<ul>
<li>Não usar declarações preparadas</li>
</ul>
<p>O uso de instruções preparadas em SQL torna as consultas mais eficientes e seguras.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/78-sql/prepared-statements"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<ul>
<li>Tratamento incorreto de valores nulos</li>
</ul>
<p>Lide com colunas anuláveis em tabelas usando ponteiros ou tipos <code>sql.NullXXX</code>.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/78-sql/null-values/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<ul>
<li>Não tratando de erros de iteração de linhas</li>
</ul>
<p>Chame o método <code>Err</code> de <code>sql.Rows</code> iterações posteriores à linha para garantir que você não perdeu nenhum erro ao preparar a próxima linha.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/78-sql/rows-iterations-errors"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="nao-fechando-recursos-transitorios-body-http-sqlrows-e-osfile-79">Não fechando recursos transitórios (body HTTP, <code>sql.Rows</code> e <code>os.File</code>) (#79)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Eventualmente feche todas as estruturas implementadas <code>io.Closer</code> para evitar possíveis vazamentos.</p>
</details>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/79-closing-resources/"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="esquecendo-a-instrucao-return-apos-responder-a-uma-solicitacao-http-80">Esquecendo a instrução return após responder a uma solicitação HTTP (#80)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Para evitar comportamentos inesperados nas implementações do manipulador HTTP, certifique-se de não perder a instrução <code>return</code> se quiser que um manipulador pare após <code>http.Error</code>.</p>
</details>
<p>Consider the following HTTP handler that handles an error from <code>foo</code> using <code>http.Error</code>:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-65-1"><a id="__codelineno-65-1" name="__codelineno-65-1" href="#__codelineno-65-1"></a><span class="kd">func</span><span class="w"> </span><span class="nx">handler</span><span class="p">(</span><span class="nx">w</span><span class="w"> </span><span class="nx">http</span><span class="p">.</span><span class="nx">ResponseWriter</span><span class="p">,</span><span class="w"> </span><span class="nx">req</span><span class="w"> </span><span class="o">*</span><span class="nx">http</span><span class="p">.</span><span class="nx">Request</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-65-2"><a id="__codelineno-65-2" name="__codelineno-65-2" href="#__codelineno-65-2"></a><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">foo</span><span class="p">(</span><span class="nx">req</span><span class="p">)</span>
</span><span id="__span-65-3"><a id="__codelineno-65-3" name="__codelineno-65-3" href="#__codelineno-65-3"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-65-4"><a id="__codelineno-65-4" name="__codelineno-65-4" href="#__codelineno-65-4"></a><span class="w"> </span><span class="nx">http</span><span class="p">.</span><span class="nx">Error</span><span class="p">(</span><span class="nx">w</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;foo&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">http</span><span class="p">.</span><span class="nx">StatusInternalServerError</span><span class="p">)</span>
</span><span id="__span-65-5"><a id="__codelineno-65-5" name="__codelineno-65-5" href="#__codelineno-65-5"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-65-6"><a id="__codelineno-65-6" name="__codelineno-65-6" href="#__codelineno-65-6"></a>
</span><span id="__span-65-7"><a id="__codelineno-65-7" name="__codelineno-65-7" href="#__codelineno-65-7"></a><span class="w"> </span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">_</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">w</span><span class="p">.</span><span class="nx">Write</span><span class="p">([]</span><span class="nb">byte</span><span class="p">(</span><span class="s">&quot;all good&quot;</span><span class="p">))</span>
</span><span id="__span-65-8"><a id="__codelineno-65-8" name="__codelineno-65-8" href="#__codelineno-65-8"></a><span class="w"> </span><span class="nx">w</span><span class="p">.</span><span class="nx">WriteHeader</span><span class="p">(</span><span class="nx">http</span><span class="p">.</span><span class="nx">StatusCreated</span><span class="p">)</span>
</span><span id="__span-65-9"><a id="__codelineno-65-9" name="__codelineno-65-9" href="#__codelineno-65-9"></a><span class="p">}</span>
</span></code></pre></div>
<p>If we run this code and <code>err != nil</code>, the HTTP response would be:</p>
<div class="language-text highlight"><pre><span></span><code><span id="__span-66-1"><a id="__codelineno-66-1" name="__codelineno-66-1" href="#__codelineno-66-1"></a>foo
</span><span id="__span-66-2"><a id="__codelineno-66-2" name="__codelineno-66-2" href="#__codelineno-66-2"></a>all good
</span></code></pre></div>
<p>The response contains both the error and success messages, and also the first HTTP status code, 500. There would also be a warning log indicating that we attempted to write the status code multiple times:</p>
<div class="language-text highlight"><pre><span></span><code><span id="__span-67-1"><a id="__codelineno-67-1" name="__codelineno-67-1" href="#__codelineno-67-1"></a>2023/10/10 16:45:33 http: superfluous response.WriteHeader call from main.handler (main.go:20)
</span></code></pre></div>
<p>The mistake in this code is that <code>http.Error</code> does not stop the handler's execution, which means the success message and status code get written in addition to the error. Beyond an incorrect response, failing to return after writing an error can lead to the unwanted execution of code and unexpected side-effects. The following code adds the <code>return</code> statement following the <code>http.Error</code> and exhibits the desired behavior when ran:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-68-1"><a id="__codelineno-68-1" name="__codelineno-68-1" href="#__codelineno-68-1"></a><span class="kd">func</span><span class="w"> </span><span class="nx">handler</span><span class="p">(</span><span class="nx">w</span><span class="w"> </span><span class="nx">http</span><span class="p">.</span><span class="nx">ResponseWriter</span><span class="p">,</span><span class="w"> </span><span class="nx">req</span><span class="w"> </span><span class="o">*</span><span class="nx">http</span><span class="p">.</span><span class="nx">Request</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-68-2"><a id="__codelineno-68-2" name="__codelineno-68-2" href="#__codelineno-68-2"></a><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">foo</span><span class="p">(</span><span class="nx">req</span><span class="p">)</span>
</span><span id="__span-68-3"><a id="__codelineno-68-3" name="__codelineno-68-3" href="#__codelineno-68-3"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-68-4"><a id="__codelineno-68-4" name="__codelineno-68-4" href="#__codelineno-68-4"></a><span class="w"> </span><span class="nx">http</span><span class="p">.</span><span class="nx">Error</span><span class="p">(</span><span class="nx">w</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;foo&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">http</span><span class="p">.</span><span class="nx">StatusInternalServerError</span><span class="p">)</span>
</span><span id="__span-68-5"><a id="__codelineno-68-5" name="__codelineno-68-5" href="#__codelineno-68-5"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="c1">// Adds the return statement</span>
</span><span id="__span-68-6"><a id="__codelineno-68-6" name="__codelineno-68-6" href="#__codelineno-68-6"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-68-7"><a id="__codelineno-68-7" name="__codelineno-68-7" href="#__codelineno-68-7"></a>
</span><span id="__span-68-8"><a id="__codelineno-68-8" name="__codelineno-68-8" href="#__codelineno-68-8"></a><span class="w"> </span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">_</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">w</span><span class="p">.</span><span class="nx">Write</span><span class="p">([]</span><span class="nb">byte</span><span class="p">(</span><span class="s">&quot;all good&quot;</span><span class="p">))</span>
</span><span id="__span-68-9"><a id="__codelineno-68-9" name="__codelineno-68-9" href="#__codelineno-68-9"></a><span class="w"> </span><span class="nx">w</span><span class="p">.</span><span class="nx">WriteHeader</span><span class="p">(</span><span class="nx">http</span><span class="p">.</span><span class="nx">StatusCreated</span><span class="p">)</span>
</span><span id="__span-68-10"><a id="__codelineno-68-10" name="__codelineno-68-10" href="#__codelineno-68-10"></a><span class="p">}</span>
</span></code></pre></div>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/80-http-return/main.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="usando-o-cliente-e-servidor-http-padrao-81">Usando o cliente e servidor HTTP padrão (#81)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Para aplicativos de nível de produção, não use as implementações de cliente e servidor HTTP padrão. Essas implementações não possuem tempos limite e comportamentos que deveriam ser obrigatórios na produção.</p>
</details>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/81-default-http-client-server/"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h2 id="teste">Teste</h2>
<h3 id="nao-categorizar-testes-tags-de-construcao-variaveis-de-ambiente-e-modo-abreviado-82">Não categorizar testes (tags de construção, variáveis de ambiente e modo abreviado) (#82)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Categorizar testes usando sinalizadores de construção, variáveis de ambiente ou modo curto torna o processo de teste mais eficiente. Você pode criar categorias de teste usando sinalizadores de construção ou variáveis de ambiente (por exemplo, testes de unidade versus testes de integração) e diferenciar testes curtos de testes de longa duração para decidir quais tipos de testes executar.</p>
</details>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/82-categorizing-tests/"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="nao-habilitando-a-bandeira-de-corrida-83">Não habilitando a bandeira de corrida (#83)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>A ativação do sinalizador <code>-race</code> é altamente recomendada ao escrever aplicativos simultâneos. Isso permite que você detecte possíveis corridas de dados que podem levar a bugs de software.</p>
</details>
<p>In Go, the race detector isnt a static analysis tool used during compilation; instead, its a tool to find data races that occur at runtime. To enable it, we have to enable the -race flag while compiling or running a test. For example:</p>
<div class="language-bash highlight"><pre><span></span><code><span id="__span-69-1"><a id="__codelineno-69-1" name="__codelineno-69-1" href="#__codelineno-69-1"></a>go<span class="w"> </span><span class="nb">test</span><span class="w"> </span>-race<span class="w"> </span>./...
</span></code></pre></div>
<p>Once the race detector is enabled, the compiler instruments the code to detect data races. Instrumentation refers to a compiler adding extra instructions: here, tracking all memory accesses and recording when and how they occur.</p>
<p>Enabling the race detector adds an overhead in terms of memory and execution time; hence, it's generally recommended to enable it only during local testing or continuous integration, not production.</p>
<p>If a race is detected, Go raises a warning. For example:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-70-1"><a id="__codelineno-70-1" name="__codelineno-70-1" href="#__codelineno-70-1"></a><span class="kn">package</span><span class="w"> </span><span class="nx">main</span>
</span><span id="__span-70-2"><a id="__codelineno-70-2" name="__codelineno-70-2" href="#__codelineno-70-2"></a>
</span><span id="__span-70-3"><a id="__codelineno-70-3" name="__codelineno-70-3" href="#__codelineno-70-3"></a><span class="kn">import</span><span class="w"> </span><span class="p">(</span>
</span><span id="__span-70-4"><a id="__codelineno-70-4" name="__codelineno-70-4" href="#__codelineno-70-4"></a><span class="w"> </span><span class="s">&quot;fmt&quot;</span>
</span><span id="__span-70-5"><a id="__codelineno-70-5" name="__codelineno-70-5" href="#__codelineno-70-5"></a><span class="p">)</span>
</span><span id="__span-70-6"><a id="__codelineno-70-6" name="__codelineno-70-6" href="#__codelineno-70-6"></a>
</span><span id="__span-70-7"><a id="__codelineno-70-7" name="__codelineno-70-7" href="#__codelineno-70-7"></a><span class="kd">func</span><span class="w"> </span><span class="nx">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-70-8"><a id="__codelineno-70-8" name="__codelineno-70-8" href="#__codelineno-70-8"></a><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="mi">0</span>
</span><span id="__span-70-9"><a id="__codelineno-70-9" name="__codelineno-70-9" href="#__codelineno-70-9"></a><span class="w"> </span><span class="k">go</span><span class="w"> </span><span class="kd">func</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="w"> </span><span class="p">}()</span>
</span><span id="__span-70-10"><a id="__codelineno-70-10" name="__codelineno-70-10" href="#__codelineno-70-10"></a><span class="w"> </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span>
</span><span id="__span-70-11"><a id="__codelineno-70-11" name="__codelineno-70-11" href="#__codelineno-70-11"></a><span class="p">}</span>
</span></code></pre></div>
<p>Runnig this code with the <code>-race</code> logs the following warning:</p>
<div class="language-bash highlight"><pre><span></span><code><span id="__span-71-1"><a id="__codelineno-71-1" name="__codelineno-71-1" href="#__codelineno-71-1"></a><span class="o">==================</span>
</span><span id="__span-71-2"><a id="__codelineno-71-2" name="__codelineno-71-2" href="#__codelineno-71-2"></a>WARNING:<span class="w"> </span>DATA<span class="w"> </span>RACE
</span><span id="__span-71-3"><a id="__codelineno-71-3" name="__codelineno-71-3" href="#__codelineno-71-3"></a><span class="hll">Write<span class="w"> </span>at<span class="w"> </span>0x00c000026078<span class="w"> </span>by<span class="w"> </span>goroutine<span class="w"> </span><span class="m">7</span>:<span class="w"> </span><span class="c1"># (1)</span>
</span></span><span id="__span-71-4"><a id="__codelineno-71-4" name="__codelineno-71-4" href="#__codelineno-71-4"></a><span class="w"> </span>main.main.func1<span class="o">()</span>
</span><span id="__span-71-5"><a id="__codelineno-71-5" name="__codelineno-71-5" href="#__codelineno-71-5"></a><span class="w"> </span>/tmp/app/main.go:9<span class="w"> </span>+0x4e
</span><span id="__span-71-6"><a id="__codelineno-71-6" name="__codelineno-71-6" href="#__codelineno-71-6"></a>
</span><span id="__span-71-7"><a id="__codelineno-71-7" name="__codelineno-71-7" href="#__codelineno-71-7"></a><span class="hll">Previous<span class="w"> </span><span class="nb">read</span><span class="w"> </span>at<span class="w"> </span>0x00c000026078<span class="w"> </span>by<span class="w"> </span>main<span class="w"> </span>goroutine:<span class="w"> </span><span class="c1"># (2)</span>
</span></span><span id="__span-71-8"><a id="__codelineno-71-8" name="__codelineno-71-8" href="#__codelineno-71-8"></a><span class="w"> </span>main.main<span class="o">()</span>
</span><span id="__span-71-9"><a id="__codelineno-71-9" name="__codelineno-71-9" href="#__codelineno-71-9"></a><span class="w"> </span>/tmp/app/main.go:10<span class="w"> </span>+0x88
</span><span id="__span-71-10"><a id="__codelineno-71-10" name="__codelineno-71-10" href="#__codelineno-71-10"></a>
</span><span id="__span-71-11"><a id="__codelineno-71-11" name="__codelineno-71-11" href="#__codelineno-71-11"></a><span class="hll">Goroutine<span class="w"> </span><span class="m">7</span><span class="w"> </span><span class="o">(</span>running<span class="o">)</span><span class="w"> </span>created<span class="w"> </span>at:<span class="w"> </span><span class="c1"># (3)</span>
</span></span><span id="__span-71-12"><a id="__codelineno-71-12" name="__codelineno-71-12" href="#__codelineno-71-12"></a><span class="w"> </span>main.main<span class="o">()</span>
</span><span id="__span-71-13"><a id="__codelineno-71-13" name="__codelineno-71-13" href="#__codelineno-71-13"></a><span class="w"> </span>/tmp/app/main.go:9<span class="w"> </span>+0x7a
</span><span id="__span-71-14"><a id="__codelineno-71-14" name="__codelineno-71-14" href="#__codelineno-71-14"></a><span class="o">==================</span>
</span></code></pre></div>
<ol>
<li>Indicates that goroutine 7 was writing</li>
<li>Indicates that the main goroutine was reading</li>
<li>Indicates when the goroutine 7 was created</li>
</ol>
<p>Lets make sure we are comfortable reading these messages. Go always logs the following:</p>
<ul>
<li>The concurrent goroutines that are incriminated: here, the main goroutine and goroutine 7.</li>
<li>Where accesses occur in the code: in this case, lines 9 and 10.</li>
<li>When these goroutines were created: goroutine 7 was created in main().</li>
</ul>
<p>In addition, if a specific file contains tests that lead to data races, we can exclude it <span class="twemoji" title="temporarily! 😉"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M11 9h2V7h-2m1 13c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8m0-18A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10A10 10 0 0 0 12 2m-1 15h2v-6h-2v6Z"/></svg></span> from race detection using the <code>!race</code> build tag:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-72-1"><a id="__codelineno-72-1" name="__codelineno-72-1" href="#__codelineno-72-1"></a><span class="c1">//go:build !race</span>
</span><span id="__span-72-2"><a id="__codelineno-72-2" name="__codelineno-72-2" href="#__codelineno-72-2"></a>
</span><span id="__span-72-3"><a id="__codelineno-72-3" name="__codelineno-72-3" href="#__codelineno-72-3"></a><span class="kn">package</span><span class="w"> </span><span class="nx">main</span>
</span><span id="__span-72-4"><a id="__codelineno-72-4" name="__codelineno-72-4" href="#__codelineno-72-4"></a>
</span><span id="__span-72-5"><a id="__codelineno-72-5" name="__codelineno-72-5" href="#__codelineno-72-5"></a><span class="kn">import</span><span class="w"> </span><span class="p">(</span>
</span><span id="__span-72-6"><a id="__codelineno-72-6" name="__codelineno-72-6" href="#__codelineno-72-6"></a><span class="w"> </span><span class="s">&quot;testing&quot;</span>
</span><span id="__span-72-7"><a id="__codelineno-72-7" name="__codelineno-72-7" href="#__codelineno-72-7"></a><span class="p">)</span>
</span><span id="__span-72-8"><a id="__codelineno-72-8" name="__codelineno-72-8" href="#__codelineno-72-8"></a>
</span><span id="__span-72-9"><a id="__codelineno-72-9" name="__codelineno-72-9" href="#__codelineno-72-9"></a><span class="kd">func</span><span class="w"> </span><span class="nx">TestFoo</span><span class="p">(</span><span class="nx">t</span><span class="w"> </span><span class="o">*</span><span class="nx">testing</span><span class="p">.</span><span class="nx">T</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-72-10"><a id="__codelineno-72-10" name="__codelineno-72-10" href="#__codelineno-72-10"></a><span class="w"> </span><span class="c1">// ...</span>
</span><span id="__span-72-11"><a id="__codelineno-72-11" name="__codelineno-72-11" href="#__codelineno-72-11"></a><span class="p">}</span>
</span></code></pre></div>
<h3 id="nao-usar-modos-de-execucao-de-teste-paralelo-e-aleatorio-84">Não usar modos de execução de teste (paralelo e aleatório) (#84)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Usar o sinalizador <code>-parallel</code> é uma forma eficiente de acelerar testes, especialmente os de longa duração. Use o sinalizador <code>-shuffle</code> para ajudar a garantir que um conjunto de testes não se baseie em suposições erradas que possam ocultar bugs.</p>
</details>
<h3 id="nao-usar-testes-baseados-em-tabela-85">Não usar testes baseados em tabela (#85)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Os testes baseados em tabelas são uma maneira eficiente de agrupar um conjunto de testes semelhantes para evitar a duplicação de código e facilitar o manuseio de atualizações futuras.</p>
</details>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/85-table-driven-tests/main_test.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="dormindo-em-testes-unitarios-86">Dormindo em testes unitários (#86)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Evite interrupções usando a sincronização para tornar o teste menos instável e mais robusto. Se a sincronização não for possível, considere uma abordagem de nova tentativa.</p>
</details>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/86-sleeping/main_test.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="nao-lidar-com-a-api-de-tempo-de-forma-eficiente-87">Não lidar com a API de tempo de forma eficiente (#87)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Entender como lidar com funções usando a API time é outra maneira de tornar um teste menos complicado. Você pode usar técnicas padrão, como lidar com o tempo como parte de uma dependência oculta ou solicitar que os clientes o forneçam.</p>
</details>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/87-time-api/"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="nao-usar-pacotes-de-utilitarios-de-teste-httptest-e-iotest-88">Não usar pacotes de utilitários de teste ( <code>httptest</code> e <code>iotest</code>) (#88)</h3>
<ul>
<li>O pacote <code>httptest</code> é útil para lidar com aplicativos HTTP. Ele fornece um conjunto de utilitários para testar clientes e servidores.</li>
</ul>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/88-utility-package/httptest/main_test.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<ul>
<li>O pacote <code>iotest</code> ajuda a escrever io.Reader e testar se um aplicativo é tolerante a erros.</li>
</ul>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/88-utility-package/iotest/main_test.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="escrevendo-benchmarks-imprecisos-89">Escrevendo benchmarks imprecisos (#89)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Regarding benchmarks:</p>
<ul>
<li>Use métodos de tempo para preservar a precisão de um benchmark.</li>
<li>Aumentar o tempo de teste ou usar ferramentas como o benchstat pode ser útil ao lidar com micro-benchmarks.</li>
<li>Tenha cuidado com os resultados de um micro-benchmark se o sistema que executa o aplicativo for diferente daquele que executa o micro-benchmark.</li>
<li>Certifique-se de que a função em teste cause um efeito colateral, para evitar que as otimizações do compilador enganem você sobre os resultados do benchmark.</li>
<li>Para evitar o efeito observador, force um benchmark a recriar os dados usados por uma função vinculada à CPU.</li>
</ul>
</details>
<p>Leia a seção completa <a href="../89-benchmarks/">aqui</a>.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/89-benchmark/"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="nao-explorando-todos-os-recursos-de-teste-do-go-90">Não explorando todos os recursos de teste do Go (#90)</h3>
<ul>
<li>Cobertura de código</li>
</ul>
<p>Use a cobertura de código com o sinalizador <code>-coverprofile</code> para ver rapidamente qual parte do código precisa de mais atenção.</p>
<ul>
<li>Testando de um pacote diferente</li>
</ul>
<p>Coloque os testes unitários em um pacote diferente para impor testes de escrita que se concentrem em um comportamento exposto, não em internos.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/90-testing-features/different-package/main_test.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<ul>
<li>Funções utilitárias</li>
</ul>
<p>O tratamento de erros usando a variável <code>*testing.T</code> em vez do clássico <code>if err != nil</code> torna o código mais curto e fácil de ler.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/90-testing-features/utility-function/main_test.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<ul>
<li>Configuração e desmontagem</li>
</ul>
<p>Você pode usar funções de setup e teardown para configurar um ambiente complexo, como no caso de testes de integração.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/90-testing-features/setup-teardown/main_test.go"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="nao-usar-fuzzing-erro-da-comunidade">Não usar fuzzing (erro da comunidade)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Fuzzing é uma estratégia eficiente para detectar entradas aleatórias, inesperadas ou malformadas em funções e métodos complexos, a fim de descobrir vulnerabilidades, bugs ou até mesmo travamentos potenciais.</p>
</details>
<p>Credits: <a href="https://github.com/jeromedoucet">@jeromedoucet</a></p>
<h2 id="otimizacoes">Otimizações</h2>
<h3 id="nao-entendendo-os-caches-da-cpu-91">Não entendendo os caches da CPU (#91)</h3>
<ul>
<li>Arquitetura da CPU</li>
</ul>
<p>Compreender como usar caches de CPU é importante para otimizar aplicativos vinculados à CPU porque o cache L1 é cerca de 50 a 100 vezes mais rápido que a memória principal.</p>
<ul>
<li>Linha de cache</li>
</ul>
<p>Estar consciente do conceito de linha de cache é fundamental para entender como organizar dados em aplicativos com uso intensivo de dados. Uma CPU não busca memória palavra por palavra; em vez disso, geralmente copia um bloco de memória para uma linha de cache de 64 bytes. Para aproveitar ao máximo cada linha de cache individual, imponha a localidade espacial.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/91-cpu-caches/cache-line/"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<ul>
<li>Slice de estruturas vs. estrutura de slices</li>
</ul>
<!-- TODO -->
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/91-cpu-caches/slice-structs/"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<ul>
<li>Previsibilidade</li>
</ul>
<p>Tornar o código previsível para a CPU também pode ser uma forma eficiente de otimizar certas funções. Por exemplo, uma passada unitária ou constante é previsível para a CPU, mas uma passada não unitária (por exemplo, uma lista vinculada) não é previsível.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/91-cpu-caches/predictability/"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<ul>
<li>Política de posicionamento de cache</li>
</ul>
<p>Para evitar um avanço crítico e, portanto, utilizar apenas uma pequena parte do cache, esteja ciente de que os caches são particionados.</p>
<h3 id="escrevendo-codigo-simultaneo-que-leva-a-compartilhamento-falso-92">Escrevendo código simultâneo que leva a compartilhamento falso (#92)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Saber que níveis mais baixos de caches de CPU não são compartilhados entre todos os núcleos ajuda a evitar padrões que degradam o desempenho, como compartilhamento falso ao escrever código de simultaneidade. Compartilhar memória é uma ilusão.</p>
</details>
<p>Leia a seção completa <a href="../92-false-sharing/">aqui</a>.</p>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/92-false-sharing/"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="nao-levando-em-consideracao-o-paralelismo-no-nivel-de-instrucao-93">Não levando em consideração o paralelismo no nível de instrução (#93)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Use o <abbr title="Instruction-Level Parallelism">ILP</abbr> para otimizar partes específicas do seu código para permitir que uma CPU execute tantas instruções paralelas quanto possível. Identificar perigos nos dados é uma das etapas principais.</p>
</details>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/93-instruction-level-parallelism/"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="nao-estar-ciente-do-alinhamento-dos-dados-94">Não estar ciente do alinhamento dos dados (#94)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Você pode evitar erros comuns lembrando que no Go os tipos básicos são alinhados com seu próprio tamanho. Por exemplo, tenha em mente que reorganizar os campos de uma estrutura por tamanho em ordem decrescente pode levar a estruturas mais compactas (menos alocação de memória e potencialmente uma melhor localidade espacial).</p>
</details>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/94-data-alignment/"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="nao-entendendo-stack-vs-heap-95">Não entendendo stack vs. heap (#95)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Compreender as diferenças fundamentais entre heap e pilha também deve fazer parte do seu conhecimento básico ao otimizar um aplicativo Go. As alocações de pilha são quase gratuitas, enquanto as alocações de heap são mais lentas e dependem do <abbr title="Garbage Collector">GC</abbr> para limpar a memória.</p>
</details>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/95-stack-heap/"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="nao-saber-como-reduzir-alocacoes-mudanca-de-api-otimizacoes-de-compilador-e-syncpool-96">Não saber como reduzir alocações (mudança de API, otimizações de compilador e <code>sync.Pool</code>) (#96)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>A redução das alocações também é um aspecto essencial da otimização de um aplicativo Go. Isso pode ser feito de diferentes maneiras, como projetar a API cuidadosamente para evitar compartilhamento, compreender as otimizações comuns do compilador Go e usar <code>sync.Pool</code>.</p>
</details>
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/96-reduce-allocations/"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span> Código fonte</a></p>
<h3 id="nao-dependendo-do-inlining-97">Não dependendo do inlining (#97)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Use a técnica de inlining de caminho rápido para reduzir com eficiência o tempo amortizado para chamar uma função.</p>
</details>
<h3 id="nao-usar-ferramentas-de-diagnostico-go-98">Não usar ferramentas de diagnóstico Go (#98)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Confie na criação de perfil e no rastreador de execução para entender o desempenho de um aplicativo e as partes a serem otimizadas.</p>
</details>
<p>Leia a seção completa <a href="../98-profiling-execution-tracing/">aqui</a>.</p>
<h3 id="nao-entendendo-como-funciona-o-gc-99">Não entendendo como funciona o <abbr title="Garbage Collector">GC</abbr> (#99)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Compreender como ajustar o <abbr title="Garbage Collector">GC</abbr> pode levar a vários benefícios, como lidar com aumentos repentinos de carga com mais eficiência.</p>
</details>
<h3 id="nao-entendendo-os-impactos-da-execucao-do-go-no-docker-e-kubernetes-100">Não entendendo os impactos da execução do Go no Docker e Kubernetes (#100)</h3>
<details class="info" open="open">
<summary>TL;DR</summary>
<p>Para ajudar a evitar a limitação da CPU quando implantado no Docker e no Kubernetes, lembre-se de que Go não reconhece <abbr title="Completely Fair Scheduler">CFS</abbr>.</p>
</details>
<p>By default, <abbr title="The variable defines the limit of OS threads in charge of executing user-level code simultaneously">GOMAXPROCS</abbr> is set to the number of OS-apparent logical CPU cores.</p>
<p>When running some Go code inside Docker and Kubernetes, we must know that Go isn't <abbr title="Completely Fair Scheduler">CFS</abbr>-aware (<a href="https://github.com/golang/go/issues/33803">github.com/golang/go/issues/33803</a>). Therefore, <abbr title="The variable defines the limit of OS threads in charge of executing user-level code simultaneously">GOMAXPROCS</abbr> isn't automatically set to the value of <code>spec.containers.resources.limits.cpu</code> (see <a href="https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/">Kubernetes Resource Management for Pods and Containers</a>); instead, it's set to the number of logical cores on the host machine. The main implication is that it can lead to an increased tail latency in some specific situations.</p>
<p>One solution is to rely on <a href="https://github.com/uber-go/automaxprocs">uber-go/automaxprocs</a> that automatically set <code>GOMAXPROCS</code> to match the Linux container CPU quota.</p>
<h2 id="community">Community</h2>
<p>Thanks to all the contributors:</p>
<p><a href="https://contrib.rocks/image?repo=teivah/100-go-mistakes">
<a class="glightbox" href="https://contrib.rocks/image?repo=teivah/100-go-mistakes" data-type="image" data-width="auto" data-height="auto" data-desc-position="bottom"><img src="https://contrib.rocks/image?repo=teivah/100-go-mistakes" alt="Description of the image"></a>
</a></p>
<h2 id="__comments">Comments</h2>
<!-- Insert generated snippet here -->
<script src="https://giscus.app/client.js"
data-repo="teivah/100-go-mistakes"
data-repo-id="MDEwOlJlcG9zaXRvcnkzMjA4MTg5NjI="
data-category="Discussions"
data-category-id="DIC_kwDOEx9PEs4CZQUm"
data-mapping="pathname"
data-strict="0"
data-reactions-enabled="1"
data-emit-metadata="0"
data-input-position="bottom"
data-theme="preferred_color_scheme"
data-lang="en"
crossorigin="anonymous"
async>
</script>
<!-- Synchronize Giscus theme with palette -->
<script>
var giscus = document.querySelector("script[src*=giscus]")
// Set palette on initial load
var palette = __md_get("__palette")
if (palette && typeof palette.color === "object") {
var theme = palette.color.scheme === "slate"
? "transparent_dark"
: "light"
// Instruct Giscus to set theme
giscus.setAttribute("data-theme", theme)
}
// Register event handlers after documented loaded
document.addEventListener("DOMContentLoaded", function() {
var ref = document.querySelector("[data-md-component=palette]")
ref.addEventListener("change", function() {
var palette = __md_get("__palette")
if (palette && typeof palette.color === "object") {
var theme = palette.color.scheme === "slate"
? "transparent_dark"
: "light"
// Instruct Giscus to change theme
var frame = document.querySelector(".giscus-frame")
frame.contentWindow.postMessage(
{ giscus: { setConfig: { theme } } },
"https://giscus.app"
)
}
})
})
</script>
</article>
</div>
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
<div class="md-copyright__highlight">
Copyright &copy; 2022 - 2024 Teiva Harsanyi
</div>
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
</div>
<div class="md-social">
<a href="https://twitter.com/teivah" target="_blank" rel="noopener" title="twitter.com" class="md-social__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/></svg>
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"base": "..", "features": ["navigation.tabs", "navigation.tabs.sticky", "search.highlight", "search.share", "search.suggest", "content.code.copy", "navigation.expand", "navigation.sections", "announce.dismiss", "toc.follow", "content.code.annotate", "content.tooltips"], "search": "../assets/javascripts/workers/search.b8dbb3d2.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
<script src="../assets/javascripts/bundle.8fd75fb4.min.js"></script>
<script>document$.subscribe(() => {const lightbox = GLightbox({"touchNavigation": true, "loop": false, "zoomable": true, "draggable": true, "openEffect": "zoom", "closeEffect": "zoom", "slideEffect": "slide"});})</script></body>
</html>