<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Programming on Flavio Silva</title><link>https://fsilva.me/tags/programming/</link><description>Recent content in Programming on Flavio Silva</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><managingEditor>flavio1110@gmail.com (Flavio Silva)</managingEditor><webMaster>flavio1110@gmail.com (Flavio Silva)</webMaster><lastBuildDate>Tue, 26 Dec 2023 14:00:00 +0100</lastBuildDate><atom:link href="https://fsilva.me/tags/programming/feed.xml" rel="self" type="application/rss+xml"/><item><title>🧹 Tidy First? By Kent Beck - My review and takeaways</title><link>https://fsilva.me/posts/tidy-first-review/</link><pubDate>Tue, 26 Dec 2023 14:00:00 +0100</pubDate><author>flavio1110@gmail.com (Flavio Silva)</author><guid>https://fsilva.me/posts/tidy-first-review/</guid><description>&lt;img src="https://fsilva.me/posts/tidy-first-review/tidy_first.jpeg" alt="Featured image of post 🧹 Tidy First? By Kent Beck - My review and takeaways" /&gt;&lt;blockquote&gt;
 &lt;p&gt;&amp;ldquo;Messy code is a nuisance. &amp;ldquo;Tidying&amp;rdquo; code, to make it more readable, requires breaking it up into manageable sections. In this practical guide, author Kent Beck, creator of Extreme Programming and pioneer of software patterns, suggests when and where you might apply tidyings to improve your code while keeping the overall structure of the system in mind. (&amp;hellip;)&amp;rdquo; &lt;a class="link" href="https://www.oreilly.com/library/view/tidy-first/9781098151232/" target="_blank" rel="noopener"
 &gt;O&amp;rsquo;Reilly - Tidy First&lt;/a&gt;&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;The book is clear, objective, and easy to read. Its simple explanations and examples on empirical software design carry sophisticated concepts on evaluating when, how, what, and if to tidy at all.&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;TL;DR: The book is an 8/10 and I recommend it to any programmer at any level of experience. It&amp;rsquo;s not a 10/10 because the first section about actual tydings with practical examples felt a bit unnecessary. I understand why it&amp;rsquo;s there, but the discussions presented in sections 2 and 3 were way more valuable for me. It might be the other way around depending on the experience though.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="sections"&gt;Sections
&lt;/h2&gt;&lt;p&gt;The author split the book into three sections: Tidyngs, Managing, and Theory.&lt;/p&gt;
&lt;h3 id="tydings"&gt;Tydings
&lt;/h3&gt;&lt;p&gt;According to Kent Beck, tidyings are a subset of refactoring. Tydings are the cute, fuzzy little refactorings that nobody could possibly hate on. In this section, the author presents several tidyings that can be done to leave things better than before, e.g. adjusting the order based on reading or cohesion, improving comments, etc.&lt;/p&gt;
&lt;p&gt;For people with little or no experience with refactorings, this is going to probably be the most valuable part.
Personally, the &amp;ldquo;nobody could possibly hate on&amp;rdquo; piece, is the highlight of this section. It helped me to create a mental model to identify the line between a tidy and a &amp;ldquo;full-blown&amp;rdquo; refactor that would require much more work and discussion.&lt;/p&gt;
&lt;h3 id="managing"&gt;Managing
&lt;/h3&gt;&lt;p&gt;&amp;ldquo;Tyding is geek self-care&amp;rdquo; - Kent Beck, Tidy First?&lt;/p&gt;
&lt;p&gt;Here is where things started to become more interesting for me. This section addresses when to start and stop tidying, and more importantly how to combine tyding, changing the structure of the code, with changing the behavior of the system.&lt;/p&gt;
&lt;p&gt;In this section is the reason why I&amp;rsquo;d love to change the title of this book is &amp;ldquo;First, After, Later, Never&amp;rdquo;. It provides a simple and objective guideline to decide when and if to tidy something. I won&amp;rsquo;t spoil it here so you can read this part from the book and reach your conclusions.&lt;/p&gt;
&lt;h3 id="theory"&gt;Theory
&lt;/h3&gt;&lt;p&gt;This was my favorite section and every chapter was very interesting to read, digest, and process. Particularly the correlation between software and cash flow versus options. This analogy helped me to think more structurally about the real cost of software, its development, and its evolution.&lt;/p&gt;
&lt;p&gt;Another highlight of this section is having a clear distinction between behavior and structural changes. Where the behavior changes are the ones related to what the software does and structural changes are the ones that support what the software needs to do. E.g. software for HR offers features like payroll, holiday planning, etc. These features are the behaviors, anything else to support these features is structural, such as the code organization, how data is stored, retrieved, etc. Understanding this distinction, their costs, and values helps to better judge when to assume debt and plan to pay/tidy.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;This book is the first of a trilogy. The upcoming books are not yet released (as of the date of writing - 22 December 2023), and they will extend the scope of changes and impact. The first one is focused on the individual programmer (you), the second will be focused on the team, and the third will focus on all stakeholders.&lt;/p&gt;</description></item><item><title>📂 Go: Importig a CSV to PostgreSQL</title><link>https://fsilva.me/posts/csv-import-go-postgresql/</link><pubDate>Sun, 26 Mar 2023 14:00:00 +0100</pubDate><author>flavio1110@gmail.com (Flavio Silva)</author><guid>https://fsilva.me/posts/csv-import-go-postgresql/</guid><description>&lt;img src="https://fsilva.me/posts/csv-import-go-postgresql/csv-rainbow.webp" alt="Featured image of post 📂 Go: Importig a CSV to PostgreSQL" /&gt;&lt;p&gt;If you are using Go ad PostgreSQL, and need to performa a bulk import a CSV,
it&amp;rsquo;s most likely you will find the &lt;code&gt;COPY&lt;/code&gt; protocol is the &lt;a class="link" href="https://www.postgresql.org/docs/current/sql-copy.html" target="_blank" rel="noopener"
 &gt;feature&lt;/a&gt; that suits you better.
In that direction, you will find examples using &lt;a class="link" href="https://github.com/jackc/pgx" target="_blank" rel="noopener"
 &gt;pgx&lt;/a&gt; &lt;a class="link" href="https://pkg.go.dev/github.com/jackc/pgx/v4#Conn.CopyFrom" target="_blank" rel="noopener"
 &gt;CopyFrom&lt;/a&gt; that relies on the native protocol, and it&amp;rsquo;s fairly easy to use.
&lt;strong&gt;However, depending how it&amp;rsquo;s used you can have an exponencial increase of memory consumption of your application making it unreliable and more expensive to run.&lt;/strong&gt;&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;TL;DR;: &lt;strong&gt;Don&amp;rsquo;t&lt;/strong&gt; load the file in memory and use &lt;code&gt;pgx.CopyFromRows&lt;/code&gt;. Instead, use the &lt;code&gt;io.Reader&lt;/code&gt; of the file and implement a custom &lt;code&gt;pgx.CopyFromSource&lt;/code&gt;.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/flavio1110/large-csv-to-pgsql" target="_blank" rel="noopener"
 &gt;Checkout the repository with examples and details presented here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="context"&gt;Context
&lt;/h3&gt;&lt;p&gt;Most of the examples out there, are either using &lt;a class="link" href="https://pkg.go.dev/github.com/jackc/pgx/v4#CopyFromRows" target="_blank" rel="noopener"
 &gt;CopyFromRows&lt;/a&gt; or &lt;a class="link" href="https://pkg.go.dev/github.com/jackc/pgx/v4#CopyFromSlice" target="_blank" rel="noopener"
 &gt;CopyFromSlice&lt;/a&gt;. However, the big problem is these two options require you to have the entire content in memory to use.
This is not a big deal when dealing with small files, there won&amp;rsquo;t be concurrent usage, or you have infinite memory 😅.&lt;/p&gt;
&lt;h3 id="how-big-is-the-problem"&gt;How big is the problem?
&lt;/h3&gt;&lt;p&gt;Comparing the memory consumption for the two distinct approaches importing a file with ~16MB (1M rows).&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Approach/metric&lt;/th&gt;
					&lt;th&gt;&lt;/th&gt;
					&lt;th style="text-align: right"&gt;TotalAlloc&lt;/th&gt;
					&lt;th&gt;&lt;/th&gt;
					&lt;th style="text-align: right"&gt;Sys&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Stream file&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;61 MiB&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;12 Mib&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Read entire file&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;84 MiB&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;58 Mib&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;&lt;strong&gt;+37.70%&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;&lt;strong&gt;+346.15%&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Yes,&lt;/strong&gt; you read it right! using &lt;code&gt;CopyFromRows&lt;/code&gt; obtained +346.15% of memory from the OS! 58 MiB instead of 12 MiB.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;You can read more about the meaning of each metric on &lt;a class="link" href="https://golang.org/pkg/runtime/#MemStats" target="_blank" rel="noopener"
 &gt;https://golang.org/pkg/runtime/#MemStats&lt;/a&gt; and find the source code and details of the comparisson on &lt;a class="link" href="https://github.com/flavio1110/large-csv-to-pgsql" target="_blank" rel="noopener"
 &gt;this repository&lt;/a&gt;..&lt;/em&gt;&lt;/p&gt;
&lt;h3 id="whats-the-most-efficient-way-for-using-the-copy-protocol-with-pgx"&gt;What&amp;rsquo;s the most efficient way for using the COPY protocol with pgx?
&lt;/h3&gt;&lt;p&gt;Instead of reading the entire in memory, the idea is to stream each line of the file directly to PostgreSQL. In this way, we only need to keep the current line in-memory as opposed to the entire file.&lt;/p&gt;
&lt;h4 id="how-can-we-do-it"&gt;How can we do it?
&lt;/h4&gt;&lt;p&gt;The &lt;a class="link" href="https://github.com/jackc/pgx/blob/master/copy_from.go#LL238C21-L238C21" target="_blank" rel="noopener"
 &gt;CopyFrom&lt;/a&gt; method receives an implementation of the interface &lt;a class="link" href="https://github.com/jackc/pgx/blob/master/copy_from.go#L68" target="_blank" rel="noopener"
 &gt;CopyFromSource&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s implement this interface using a CSV file with the followng three columns: first_name, last_name, and city.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;span class="lnt"&gt;35
&lt;/span&gt;&lt;span class="lnt"&gt;36
&lt;/span&gt;&lt;span class="lnt"&gt;37
&lt;/span&gt;&lt;span class="lnt"&gt;38
&lt;/span&gt;&lt;span class="lnt"&gt;39
&lt;/span&gt;&lt;span class="lnt"&gt;40
&lt;/span&gt;&lt;span class="lnt"&gt;41
&lt;/span&gt;&lt;span class="lnt"&gt;42
&lt;/span&gt;&lt;span class="lnt"&gt;43
&lt;/span&gt;&lt;span class="lnt"&gt;44
&lt;/span&gt;&lt;span class="lnt"&gt;45
&lt;/span&gt;&lt;span class="lnt"&gt;46
&lt;/span&gt;&lt;span class="lnt"&gt;47
&lt;/span&gt;&lt;span class="lnt"&gt;48
&lt;/span&gt;&lt;span class="lnt"&gt;49
&lt;/span&gt;&lt;span class="lnt"&gt;50
&lt;/span&gt;&lt;span class="lnt"&gt;51
&lt;/span&gt;&lt;span class="lnt"&gt;52
&lt;/span&gt;&lt;span class="lnt"&gt;53
&lt;/span&gt;&lt;span class="lnt"&gt;54
&lt;/span&gt;&lt;span class="lnt"&gt;55
&lt;/span&gt;&lt;span class="lnt"&gt;56
&lt;/span&gt;&lt;span class="lnt"&gt;57
&lt;/span&gt;&lt;span class="lnt"&gt;58
&lt;/span&gt;&lt;span class="lnt"&gt;59
&lt;/span&gt;&lt;span class="lnt"&gt;60
&lt;/span&gt;&lt;span class="lnt"&gt;61
&lt;/span&gt;&lt;span class="lnt"&gt;62
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;newPeopleCopyFromSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;csvStream&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Reader&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;peopleCopyFromSource&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;csvReader&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;csvStream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;csvReader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReuseRecord&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// reuse slice to return the record line by line&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;csvReader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FieldsPerRecord&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;peopleCopyFromSource&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;csvReader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;isBOF&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// first line is header&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;peopleColumns&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;peopleCopyFromSource&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;reader&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Reader&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;currentCsvRow&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;isEOF&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;isBOF&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pfs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;peopleCopyFromSource&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Values&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pfs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isEOF&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pfs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pfs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// the order of the elements of the record array, must match with&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// the order of the columns in passed into the copy method&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pfs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pfs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentCsvRow&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pfs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pfs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentCsvRow&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pfs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pfs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentCsvRow&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pfs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pfs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;peopleCopyFromSource&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pfs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentCsvRow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pfs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pfs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pfs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// when get to the end of the file return false and clean the error.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// If it&amp;#39;s io.EOF we can&amp;#39;t return an error&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pfs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EOF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pfs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isEOF&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pfs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pfs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isBOF&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pfs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isBOF&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pfs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pfs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;peopleCopyFromSource&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pfs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;You can now use this implementation in the &lt;code&gt;CopyFrom&lt;/code&gt; method. e.g.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pgxConn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CopyFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pgx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Identifier&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;people&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;peopleColumns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;newPeopleCopyFromSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;csvStream&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="conclusion"&gt;Conclusion
&lt;/h3&gt;&lt;p&gt;Using the &lt;code&gt;CopyFrom&lt;/code&gt; with &lt;code&gt;CopyFromRows&lt;/code&gt; or &lt;code&gt;CopyFrom&lt;/code&gt; will significantly increase the memory comsultion of your application. The high memory usage can bring several problems like OOM errors, increase of costs, unavailability, etc.&lt;/p&gt;
&lt;p&gt;By using a custom implementation of &lt;a class="link" href="https://github.com/jackc/pgx/blob/master/copy_from.go#L68" target="_blank" rel="noopener"
 &gt;CopyFromSource&lt;/a&gt; will make your application much more efficient, reliable, and cheaper to ru.&lt;/p&gt;
&lt;p&gt;You can find the entire source code of the examples above on &lt;a class="link" href="https://github.com/flavio1110/large-csv-to-pgsql" target="_blank" rel="noopener"
 &gt;this repository&lt;/a&gt;. There you will also find more deatils about the comparisson and the not-so-great implementation.&lt;/p&gt;</description></item><item><title>🔢 Go: Where is the decimal type?</title><link>https://fsilva.me/posts/go-decimal-type/</link><pubDate>Tue, 21 Mar 2023 14:00:00 +0100</pubDate><author>flavio1110@gmail.com (Flavio Silva)</author><guid>https://fsilva.me/posts/go-decimal-type/</guid><description>&lt;img src="https://fsilva.me/posts/go-decimal-type/gopher-side-eye.webp" alt="Featured image of post 🔢 Go: Where is the decimal type?" /&gt;&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt; doesn&amp;rsquo;t have a primitive &lt;code&gt;decimal&lt;/code&gt; type for arbitrary-precision fixed-point decimal numbers. Yes, you read it right. Therefore, if you need to deal with fixed-point precision there are two main options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use an external package like &lt;a class="link" href="https://github.com/shopspring/decimal" target="_blank" rel="noopener"
 &gt;decimal&lt;/a&gt;, which introduces the &lt;code&gt;decimal&lt;/code&gt; type. However, the current version (1.3.1), can &amp;ldquo;only&amp;rdquo; represent numbers with a maximum of 2^31 digits after the decimal point.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;int64&lt;/code&gt; to store and deal with these numbers. For e.g. given you need 6 precision digits, therefore &lt;code&gt;79.23&lt;/code&gt;, &lt;code&gt;23.00&lt;/code&gt;, and &lt;code&gt;54.123456&lt;/code&gt;, become respectively &lt;code&gt;79230000&lt;/code&gt;, &lt;code&gt;23000000&lt;/code&gt;, and &lt;code&gt;54123456&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There is an &lt;a class="link" href="https://github.com/golang/go/issues/19787#issue-218228389" target="_blank" rel="noopener"
 &gt;open proposal&lt;/a&gt; to add decimal float types (IEEE 754-2008) in the std lib. However, for now, it&amp;rsquo;s just a proposal being discussed, without guarantee it will be ever added.&lt;/p&gt;</description></item><item><title>🧠 Go resources for beginners</title><link>https://fsilva.me/posts/go-resources/</link><pubDate>Sun, 19 Mar 2023 14:00:00 +0100</pubDate><author>flavio1110@gmail.com (Flavio Silva)</author><guid>https://fsilva.me/posts/go-resources/</guid><description>&lt;img src="https://fsilva.me/posts/go-resources/gophers.webp" alt="Featured image of post 🧠 Go resources for beginners" /&gt;&lt;p&gt;Below a living list of compiled links for whoever is learning &lt;strong&gt;Go&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id="official-docs"&gt;Official docs
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Effective Go&lt;/strong&gt; - &lt;a class="link" href="https://go.dev/doc/effective_go" target="_blank" rel="noopener"
 &gt;https://go.dev/doc/effective_go&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A document that gives tips for writing clear, idiomatic Go code. A must-read for any new Go programmer. It augments the tour and the language specification, both of which should be read first.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Go Code Review Comments&lt;/strong&gt; &lt;a class="link" href="https://github.com/golang/go/wiki/CodeReviewComment" target="_blank" rel="noopener"
 &gt;https://github.com/golang/go/wiki/CodeReviewComment&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;This page collects common comments made during reviews of Go code, so that a single detailed explanation can be referred to by shorthands. This is a laundry list of common mistakes, not a comprehensive style guide. You can view this as a supplement to Effective Go.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Go Docs&lt;/strong&gt; - &lt;a class="link" href="https://go.dev/doc/" target="_blank" rel="noopener"
 &gt;https://go.dev/doc/&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Root for many useful documentations&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FAQ&lt;/strong&gt; - &lt;a class="link" href="https://go.dev/doc/faq" target="_blank" rel="noopener"
 &gt;https://go.dev/doc/faq&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Answers to common questions about Go.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="blogs"&gt;Blogs
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dave Cheney&lt;/strong&gt; - &lt;a class="link" href="https://dave.cheney.net/" target="_blank" rel="noopener"
 &gt;https://dave.cheney.net/&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Specially the &lt;a class="link" href="https://dave.cheney.net/practical-go" target="_blank" rel="noopener"
 &gt;practical go section&lt;/a&gt;, it has TONS of good advice and real-world examples of how to deal with daily challenges. I highly recommend it.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="courses"&gt;Courses
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The way to go&lt;/strong&gt; - &lt;a class="link" href="https://www.educative.io/courses/the-way-to-go" target="_blank" rel="noopener"
 &gt;https://www.educative.io/courses/the-way-to-go&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It&amp;rsquo;s a course from educative.io, it goes from the basics concepts of the language to more advanced ones. It also brings very interesting insights into the differences between the approaches of Java/C# to Go..&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;How to code in go&lt;/strong&gt; - &lt;a class="link" href="https://www.digitalocean.com/community/tutorial_series/how-to-code-in-go" target="_blank" rel="noopener"
 &gt;https://www.digitalocean.com/community/tutorial_series/how-to-code-in-go&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A great collection of tutorials that cover basic Go concepts, ideal for beginers&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="videos"&gt;Videos
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Go in 100 seconds&lt;/strong&gt; - &lt;a class="link" href="https://www.youtube.com/watch?v=446E-r0rXHI&amp;amp;t=38s" target="_blank" rel="noopener"
 &gt;https://www.youtube.com/watch?v=446E-r0rXHI&amp;t=38s&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Short introduction about Go&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Simplicity is complicated&lt;/strong&gt; - &lt;a class="link" href="https://www.youtube.com/watch?v=rFejpH_tAHM" target="_blank" rel="noopener"
 &gt;https://www.youtube.com/watch?v=rFejpH_tAHM&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Rob Pike talks about how Go is often described as a simple language. It is not, it just seems that way. Rob explains how Go&amp;rsquo;s simplicity hides a great deal of complexity, and that both the simplicity and complexity are part of the design.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Concurrency is not parallelism&lt;/strong&gt; - &lt;a class="link" href="https://www.youtube.com/watch?v=qmg1CF3gZQ0&amp;amp;t=1582s" target="_blank" rel="noopener"
 &gt;https://www.youtube.com/watch?v=qmg1CF3gZQ0&amp;t=1582s&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Rob Pike talks about concurrency and how Go implements it&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Understanding channels&lt;/strong&gt; - &lt;a class="link" href="https://www.youtube.com/watch?v=KBZlN0izeiY&amp;amp;t=1011s" target="_blank" rel="noopener"
 &gt;https://www.youtube.com/watch?v=KBZlN0izeiY&amp;t=1011s&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Channels provide a simple mechanism for goroutines to communicate, and a powerful construct to build sophisticated concurrency patterns. We will delve into the inner workings of channels and channel operations, including how they&amp;rsquo;re supported by the runtime scheduler and memory&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Concurrency in Go&lt;/strong&gt; - &lt;a class="link" href="https://www.youtube.com/watch?v=%5c_uQgGS_VIXM&amp;amp;list=PLsc-VaxfZl4do3Etp_xQ0aQBoC-x5BIgJ" target="_blank" rel="noopener"
 &gt;https://www.youtube.com/watch?v=\_uQgGS_VIXM&amp;list=PLsc-VaxfZl4do3Etp_xQ0aQBoC-x5BIgJ&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Playlist with a few short videos about different components of concurrency in Go&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Just for func&lt;/strong&gt; - &lt;a class="link" href="https://www.youtube.com/watch?v=H_4eRD8aegk&amp;amp;list=PL64wiCrrxh4Jisi7OcCJIUpguV_f5jGnZ" target="_blank" rel="noopener"
 &gt;https://www.youtube.com/watch?v=H_4eRD8aegk&amp;list=PL64wiCrrxh4Jisi7OcCJIUpguV_f5jGnZ&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;A very complete playlist of tutorials given by Francesc Campoy, a past Developer Advocate for the Go team at Google, that cover simple to advanced topics in Go&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Golang crash course&lt;/strong&gt; - &lt;a class="link" href="https://www.youtube.com/watch?v=SqrbIlUwR0U" target="_blank" rel="noopener"
 &gt;https://www.youtube.com/watch?v=SqrbIlUwR0U&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;A 90 minutes video that covers most of Go features with cristal clear live coding examples, excelent for beginers to get a fast gist of Go&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="podcasts"&gt;Podcasts
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Go Time&lt;/strong&gt; - &lt;a class="link" href="https://open.spotify.com/show/2cKdcxETn7jDp7uJCwqmSE" target="_blank" rel="noopener"
 &gt;Spotify&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Diverse discussions from around the Go and its community&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>