<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bjarne Magnussen</title>
    <description>The latest articles on DEV Community by Bjarne Magnussen (@bjarnemagnussen).</description>
    <link>https://dev.to/bjarnemagnussen</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F117513%2Fb0910a86-3516-41ec-9c5f-908b19670913.jpg</url>
      <title>DEV Community: Bjarne Magnussen</title>
      <link>https://dev.to/bjarnemagnussen</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bjarnemagnussen"/>
    <language>en</language>
    <item>
      <title>A Primer To Go Modules</title>
      <dc:creator>Bjarne Magnussen</dc:creator>
      <pubDate>Wed, 01 Apr 2020 13:00:48 +0000</pubDate>
      <link>https://dev.to/bjarnemagnussen/a-primer-to-go-modules-1ojp</link>
      <guid>https://dev.to/bjarnemagnussen/a-primer-to-go-modules-1ojp</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--u3ojgOUq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fjzu5a36twnxxwmxy59l.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--u3ojgOUq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fjzu5a36twnxxwmxy59l.jpg" alt="featured"&gt;&lt;/a&gt;&lt;em&gt;(Image from &lt;a href="https://www.youtube.com/watch?v=NCAIhepJgr0"&gt;https://www.youtube.com/watch?v=NCAIhepJgr0&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Go Modules was introduced in 2018 with Go version 1.11 and with the current (25th of February 2020) version 1.14 is considered ready for production use. It is fairly straight-forward and easy to use. This blog post gives some background on the historical transition to modules, what modules are and the advantages of using it.&lt;/p&gt;

&lt;h1&gt;
  
  
  What are Go Packages?
&lt;/h1&gt;

&lt;p&gt;Modules use the existing package management of Go without changing it fundamentally. To better understand them it is therefore necessary to first understand what packages are.&lt;/p&gt;

&lt;p&gt;An important and fundamental part of high-quality software is code reuse embodied in the principle “Don't Repeat Yourself” — the DRY principle. You should never repeat the same code over and over again, but instead allow it to be reused as much as possible. This also increases the maintainability of code.&lt;/p&gt;

&lt;p&gt;Packages help in organizing related Go source files together into an atomic unit. A package bundles functions and variables together and makes them available to the rest of a bigger project or to completely separate projects. This makes it easier to share code with other projects by allowing them to import and reuse it.&lt;/p&gt;

&lt;p&gt;In this way Go encourages you to write small pieces of software components through packages, and compose your applications with these small packages.&lt;/p&gt;

&lt;p&gt;Using packages has the following advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No name conflicts, since functions can have the same name while belonging to different packages.&lt;/li&gt;
&lt;li&gt;Allows reusing and sharing code among projects.&lt;/li&gt;
&lt;li&gt;Organizes related code together.&lt;/li&gt;
&lt;li&gt;Reduces compile times as packages are only re-compiled if their code is changed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Declaring a package
&lt;/h2&gt;

&lt;p&gt;A package is not much more than a directory inside your Go workspace with one or more Go source files, or other Go packages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DjSQbNBF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/uvngbdrnpovtq4zpg704.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DjSQbNBF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/uvngbdrnpovtq4zpg704.jpg" alt="golang-package-illustration"&gt;&lt;/a&gt;&lt;em&gt;(Image from &lt;a href="https://www.callicoder.com/golang-packages/"&gt;https://www.callicoder.com/golang-packages/&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Every Go source file must belong to a package, which is declared at the top of a file using the following syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;packagename&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;All functions and variables defined in this source file then become part of the declared package.&lt;/p&gt;

&lt;p&gt;You can export a member of your package by letting its declared name begin with a &lt;a href="https://tour.golang.org/basics/3"&gt;capital letter&lt;/a&gt;. Only then can other packages import and use it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Importing packages
&lt;/h2&gt;

&lt;p&gt;To import packages in Go use the &lt;code&gt;import&lt;/code&gt; syntax&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s"&gt;"fmt"&lt;/span&gt;
  &lt;span class="s"&gt;"time"&lt;/span&gt;
  &lt;span class="s"&gt;"math"&lt;/span&gt;
  &lt;span class="s"&gt;"math/rand"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The last element of the import path is the package name available for your project. For example, the package imported with &lt;code&gt;math/rand&lt;/code&gt; is simply &lt;code&gt;rand&lt;/code&gt; and its exported function &lt;a href="https://golang.org/pkg/math/rand/#Intn"&gt;&lt;code&gt;Intn(n int)&lt;/code&gt;&lt;/a&gt; can be invoked with e.g. &lt;code&gt;rand.Intn(100)&lt;/code&gt;. The package is imported with &lt;code&gt;math/rand&lt;/code&gt; because it is nested inside the &lt;code&gt;math&lt;/code&gt; package as a subdirectory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Nesting
&lt;/h3&gt;

&lt;p&gt;It is possible to nest a package inside another by creating a subdirectory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$GOPATH
└── github.com
    └── bjarnemagnussen
        └── myproject
            ├── numbers          # Some Package
            └── strings          # Another Package
                └── greet        # Nested Package
                    └── texts.go
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  The GOPATH
&lt;/h3&gt;

&lt;p&gt;All import paths for non-builtin packages are relative to its &lt;code&gt;GOPATH&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s"&gt;"github.com/bjarnemagnussen/myproject/numbers"&lt;/span&gt;
  &lt;span class="s"&gt;"github.com/bjarnemagnussen/myproject/strings"&lt;/span&gt;  
  &lt;span class="s"&gt;"github.com/bjarnemagnussen/myproject/strings/greet"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Getting 3rd Party Packages
&lt;/h3&gt;

&lt;p&gt;This makes it very easy to import third party packages. You can use the &lt;code&gt;go get&lt;/code&gt; command to download third party packages from remote repositories.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;go get &lt;span class="nt"&gt;-u&lt;/span&gt; github.com/jinzhu/gorm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The above command fetches the &lt;a href="https://github.com/jinzhu/gorm"&gt;&lt;code&gt;gorm&lt;/code&gt;&lt;/a&gt; package from Github and automatically stores it inside &lt;code&gt;GOPATH&lt;/code&gt;. To use it import the package to any of the source files in your project with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"github.com/jinzhu/gorm"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Package Alias
&lt;/h3&gt;

&lt;p&gt;What happens if different packages have the same names? Package alias can resolve naming conflicts between packages, or give a short name to an imported package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="s"&gt;"strings"&lt;/span&gt;   &lt;span class="c"&gt;// Package Alias "str"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Vendoring And Versioning
&lt;/h2&gt;

&lt;p&gt;Go packages do not provide any builtin versioning system. The &lt;a href="https://golang.org/doc/faq#get_version"&gt;Go FAQ&lt;/a&gt; suggested to create a local copy of a third party package that should stay frozen:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you're using an externally supplied package and worry that it might change in unexpected ways, the simplest solution is to copy it to your local repository. (This is the approach Google takes internally.) Store the copy under a new import path that identifies it as a local copy.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Over the years many different tools where proposed and developed around the idea of “vendoring” such as &lt;a href="https://medium.com/@forEmil/dead-simple-dependencies-in-go-3b2cb856d200"&gt;&lt;code&gt;vend&lt;/code&gt;&lt;/a&gt;, &lt;a href="http://www.getgb.io/"&gt;&lt;code&gt;gb&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://github.com/golang/dep"&gt;&lt;code&gt;dep&lt;/code&gt;&lt;/a&gt;. Around 2016 a discussion arose to &lt;a href="https://dave.cheney.net/2016/06/24/gophers-please-tag-your-releases"&gt;tag versions&lt;/a&gt; onto packages and prepare for a time when it would become valuable. The community agreed on &lt;code&gt;git&lt;/code&gt; release tags with &lt;em&gt;semantic versioning&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Semantic versioning divides releases into&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a major (breaking) version,&lt;/li&gt;
&lt;li&gt;a minor (feature) version,&lt;/li&gt;
&lt;li&gt;and a patch version.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The full version is prepended with a single “v” and looks like “v1.2.3”, which translates into a major version 1, with minor version 2 and patch version 3. When there is a bugfix the patch version is increased. If features are added that are backwards compatible the minor version is increased. For changes to the code that remove backwards compatibility the major version is increased.&lt;/p&gt;

&lt;p&gt;Version tags are used by vendoring tools such as &lt;code&gt;dep&lt;/code&gt; to define which commit state of a package to vendor. However, another approach was introduced in 2018 to completely eliminate vendoring and allow for project-based workflows instead of &lt;code&gt;GOPATH&lt;/code&gt;: Go Modules.&lt;/p&gt;

&lt;h1&gt;
  
  
  Go Modules
&lt;/h1&gt;

&lt;p&gt;Today Go modules has replaced &lt;code&gt;dep&lt;/code&gt; and followed up on the work of yet another dependency manager called &lt;a href="https://research.swtch.com/vgo-tour"&gt;&lt;code&gt;vgo&lt;/code&gt;&lt;/a&gt;. Modules is a way of packaging software and is Go's new simplistic dependency management that even allows for reproducible builds.&lt;/p&gt;

&lt;p&gt;Imagine you are developing a Go program with a number of dependencies such as package &lt;code&gt;A&lt;/code&gt;. At the time of writing your program, package &lt;code&gt;A&lt;/code&gt; works in a set way.&lt;/p&gt;

&lt;p&gt;However, what happens when the maintainers of package &lt;code&gt;A&lt;/code&gt; update their program to fix a bug or extend functionality? You might get lucky and their changes might not impact your application. However, you might be unlucky and these changes break your application.&lt;/p&gt;

&lt;p&gt;This is where Go Modules comes in to save the day. By using modules, we can select the precise versions of a dependency that we wish to use and ensure that whenever we build our program, it always uses the specified versions.&lt;/p&gt;

&lt;h2&gt;
  
  
  go.mod
&lt;/h2&gt;

&lt;p&gt;A module is just a collection of Go packages stored in a directory with a &lt;code&gt;go.mod&lt;/code&gt; file at its root. As an example the following go.mod file defines the module &lt;code&gt;github.com/my/thing&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module github.com/my/thing

require (
    github.com/some/dependency v1.2.3
    github.com/another/dependency/v4 v4.0.0
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There are four directives: &lt;code&gt;module&lt;/code&gt;, &lt;code&gt;require&lt;/code&gt;, &lt;code&gt;replace&lt;/code&gt; and &lt;code&gt;exclude&lt;/code&gt;. I refer to the excellent &lt;a href="https://github.com/golang/go/wiki/Modules#modules"&gt;Go Wiki&lt;/a&gt; page to read about the last two directives &lt;code&gt;replace&lt;/code&gt; and &lt;code&gt;exclude&lt;/code&gt;. The &lt;code&gt;require&lt;/code&gt; directive specifies the versions of the named packages that are used by this module as dependencies and will be revisited in more detail later.&lt;/p&gt;

&lt;p&gt;A &lt;em&gt;module path&lt;/em&gt; is defined with the &lt;code&gt;module&lt;/code&gt; directive. All packages in a module share the module path as a common prefix to their import paths. In other words, the module path and relative path from the &lt;code&gt;go.mod&lt;/code&gt; file to a package's directory decides its import path.&lt;/p&gt;

&lt;p&gt;For example, if you are creating a module for a repository &lt;code&gt;github.com/my/thing&lt;/code&gt; with two packages &lt;code&gt;foo&lt;/code&gt; and &lt;code&gt;bar&lt;/code&gt;, then the first line of the &lt;code&gt;go.mod&lt;/code&gt; file would declare the module path with &lt;code&gt;module github.com/my/thing&lt;/code&gt;. The corresponding directory structure could be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;thing
├── bar
|   └── bar.go
├── foo
|   └── foo.go
└── go.mod
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The import paths for the &lt;code&gt;foo&lt;/code&gt; and &lt;code&gt;bar&lt;/code&gt; packages would then be &lt;code&gt;github.com/my/thing/foo&lt;/code&gt; and &lt;code&gt;github.com/my/thing/bar&lt;/code&gt;. Hence the package foo would be imported in a Go source file with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"github.com/my/thing/foo"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Importing a module stored locally outside your &lt;code&gt;GOPATH&lt;/code&gt; from another module can be easily achieved using a VCS (e.g. github.com) for the dependency.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Go can automatically take care of downloading and importing a dependency if it is using a VCS, regardless of where its working directory is stored on disk. Alternatively, the &lt;code&gt;replace&lt;/code&gt; directive of &lt;code&gt;go.mod&lt;/code&gt; can be used to point to the dependency's local directory, see &lt;a href="https://stackoverflow.com/questions/52328952/how-to-use-a-module-that-is-outside-of-gopath-in-another-module"&gt;this answer&lt;/a&gt; on StackOverflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Version Selection
&lt;/h2&gt;

&lt;p&gt;With Go Modules, adding a new dependency to any of your Go source files will have most Go commands (such as &lt;code&gt;go build&lt;/code&gt; and &lt;code&gt;go test&lt;/code&gt;) automatically download the &lt;em&gt;highest&lt;/em&gt; version of that new package and add it as a direct dependency to the &lt;code&gt;go.mod&lt;/code&gt; file with the &lt;code&gt;require&lt;/code&gt; directive.&lt;/p&gt;

&lt;p&gt;For example, assume you create a new module from scratch with a &lt;code&gt;go.mod&lt;/code&gt; file only consisting of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module github.com/my/thing
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Adding a new import to a dependency &lt;code&gt;github.com/some/mod&lt;/code&gt;, which latest tagged release version is v1.2.3, and running &lt;code&gt;go build ./...&lt;/code&gt; will automatically download the dependency and change your &lt;code&gt;go.mod&lt;/code&gt; file to reflect the new dependency with its latest version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module github.com/my/thing

require (
  github.com/some/mod v1.2.3
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The module &lt;code&gt;github.com/some/mod&lt;/code&gt; is now a dependency with an allowed version greater than v1.2.3 but less than v2, since the assumed semantic version means that v2 is incompatible with v1.&lt;/p&gt;

&lt;p&gt;Go Modules uses a &lt;em&gt;minimal version selection&lt;/em&gt; for &lt;em&gt;indirect&lt;/em&gt; dependencies. That means that Go Modules selects the highest of the versions explicitly listed by a require directive in your module or any one of its dependencies. If your module depends on &lt;code&gt;A&lt;/code&gt; that itself has a &lt;code&gt;require D v1.0.0&lt;/code&gt; and your module also depends on &lt;code&gt;B&lt;/code&gt; that has a &lt;code&gt;require D v1.1.1&lt;/code&gt;, then Go Modules would select v1.1.1 of dependency &lt;code&gt;D&lt;/code&gt;. This selection of v1.1.1 remains consistent even if some time later a v1.2.0 of &lt;code&gt;D&lt;/code&gt; becomes available. This is in contrast to &lt;code&gt;go dep&lt;/code&gt;, which always selects the highest compatible released version under the assumption of semantic versioning.&lt;/p&gt;

&lt;p&gt;To see a list of the selected module versions (including indirect dependencies), you can use &lt;code&gt;go list -m all&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If later an indirect dependency is removed, Go Modules will still keep track of the “latest not-greatest” version. In other words, if we were to remove from our module the dependency &lt;code&gt;B&lt;/code&gt; containing a &lt;code&gt;require D v1.1.1&lt;/code&gt; but keep dependency &lt;code&gt;A&lt;/code&gt; with a &lt;code&gt;require D v1.0.0&lt;/code&gt;, then Go Modules would not fallback to v1.0.0 but instead keep v1.1.1 of &lt;code&gt;D&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Keeping track of dependency versions is done with a &lt;code&gt;go.sum&lt;/code&gt; file.&lt;/p&gt;

&lt;h2&gt;
  
  
  go.sum
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;go.sum&lt;/code&gt; file is an opaque reliability meta data file and it should not be used to understand your dependencies. Any time your Go Module downloads a version of a dependency not yet seen, that version is tagged inside the &lt;code&gt;go.sum&lt;/code&gt; file with its corresponding git commit hash acting as a cryptographic checksum.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;go.sum&lt;/code&gt; file retains checksums for dependency versions even after you stop using that particular dependency or version. This allows validation of the checksums if you later resume using something, providing additional safety. The &lt;code&gt;go.sum&lt;/code&gt; will therefore frequently have more dependency listed than your &lt;code&gt;go.mod&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your module's &lt;code&gt;go.sum&lt;/code&gt; file should always be committed along with your &lt;code&gt;go.mod&lt;/code&gt; file.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Committing &lt;code&gt;go.sum&lt;/code&gt; has the following benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If someone clones your repository and downloads your dependencies, they will receive an error if there is any mismatch between their downloaded copies of your dependencies and the corresponding entries in your &lt;code&gt;go.sum&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In addition, &lt;code&gt;go mod verify&lt;/code&gt; checks that the on-disk cached copies of module downloads still match the entries in &lt;code&gt;go.sum&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Activating And Using Modules
&lt;/h2&gt;

&lt;p&gt;Enough of the theory! Let's see how we can add Go Modules to a project and use it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--u94e11Uz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/a4y9ueodnv22m9v1c6sa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--u94e11Uz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/a4y9ueodnv22m9v1c6sa.png" alt="travlling-outside-gopath"&gt;&lt;/a&gt;&lt;em&gt;(Image from &lt;a href="https://blog.francium.tech/go-modules-go-project-set-up-without-gopath-1ae601a4e868"&gt;https://blog.francium.tech/go-modules-go-project-set-up-without-gopath-1ae601a4e868&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One of the main features of modules is to work on Go projects &lt;strong&gt;outside of&lt;/strong&gt; &lt;code&gt;GOPATH&lt;/code&gt;. We will therefore start by navigating to the root directory of some &lt;em&gt;imaginary&lt;/em&gt; project not stored in the &lt;code&gt;GOPATH&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd &amp;lt;project path outside $GOPATH/src&amp;gt;         # e.g., cd ~/projects/hello
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Create the initial module definition by automatically writing it to the &lt;code&gt;go.mod&lt;/code&gt; file with:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ go mod init
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;go mod init&lt;/code&gt; will often be able to use auxiliary data (such as VCS meta-data) to automatically determine the appropriate module path. But if &lt;code&gt;go mod init&lt;/code&gt; should state that it cannot automatically determine the module path, you can supply the module path as an optional argument with &lt;code&gt;go mod init github.com/my/thing&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build the module with
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ go build ./...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Building the module will automatically download all necessary dependencies and choose their latest versions. The direct dependencies will show up with the &lt;code&gt;require&lt;/code&gt; directive inside &lt;code&gt;go.mod&lt;/code&gt;, while both the direct and indirect dependencies are tagged to their commit hashes inside &lt;code&gt;go.sum&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It is good practice to run &lt;code&gt;go mod tidy&lt;/code&gt; before committing code to your repository.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This will ensure that the &lt;code&gt;go.mod&lt;/code&gt; file contains the dependency requirements for all possible combinations of OS, architecture, and build tags, including for testing purposes. This will help others on your team and your CI/CD environments.&lt;/p&gt;

&lt;p&gt;Running &lt;code&gt;go mod tidy&lt;/code&gt; will also fix any inconsistency reflected by a missing &lt;code&gt;go.mod&lt;/code&gt; file of a dependency of your module, e.g. because the dependency has not yet opted in to modules itself, or if its &lt;code&gt;go.mod&lt;/code&gt; file is missing one or more of its dependencies, e.g. because the module author did not run &lt;code&gt;go mod tidy&lt;/code&gt;. The missing transitive dependencies will be added to your module's requirements along with an &lt;code&gt;// indirect&lt;/code&gt; comment to indicate that the dependency is not from a direct import within your module.&lt;/p&gt;

&lt;p&gt;This behaviour is how modules provide 100% reproducible builds and tests by recording precise dependency information.&lt;/p&gt;

&lt;h2&gt;
  
  
  Updating Dependencies
&lt;/h2&gt;

&lt;p&gt;To update a specific dependency inside your module and all its indirect dependency you run as usually&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ go get -u github/some/package
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will also automatically change both &lt;code&gt;go.mod&lt;/code&gt; and &lt;code&gt;go.sum&lt;/code&gt; to reflect the new version(s).&lt;/p&gt;

&lt;p&gt;To upgrade &lt;em&gt;all direct and indirect&lt;/em&gt; dependencies to their latest versions do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Upgrading to latest minor or patch releases: &lt;code&gt;go get -u ./...&lt;/code&gt; (and add &lt;code&gt;-t&lt;/code&gt; to also upgrade test dependencies).&lt;/li&gt;
&lt;li&gt;Upgrading to latest patch releases only: &lt;code&gt;go get -u=patch ./...&lt;/code&gt; (and add &lt;code&gt;-t&lt;/code&gt; to also upgrade test dependencies).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I may have skipped a lot of small details in this post. But the idea behind Go Modules is that it should often be possible to just magically work without configuration. However, knowing some background from where Go Modules comes helps in understanding the design choices. Today Go Modules should be used with &lt;em&gt;every&lt;/em&gt; new project and can also easily be activated for existing ones.&lt;/p&gt;

</description>
      <category>go</category>
    </item>
    <item>
      <title>Enum vs Flag for bitmasks in Python</title>
      <dc:creator>Bjarne Magnussen</dc:creator>
      <pubDate>Thu, 28 Nov 2019 17:16:21 +0000</pubDate>
      <link>https://dev.to/bjarnemagnussen/enum-vs-flag-for-bitmasks-in-python-2ig8</link>
      <guid>https://dev.to/bjarnemagnussen/enum-vs-flag-for-bitmasks-in-python-2ig8</guid>
      <description>&lt;p&gt;Ever wondered what's behind those funny looking Unix access permission values like &lt;code&gt;600&lt;/code&gt; ✋, &lt;code&gt;777&lt;/code&gt; ⚠️, or &lt;code&gt;666&lt;/code&gt; 😈? Well, they are &lt;a href="https://en.wikipedia.org/wiki/File_system_permissions#Numeric_notation"&gt;octal representations&lt;/a&gt;, where each of the three rightmost digits represents a different part of the permissions for owner, group, and others.&lt;/p&gt;

&lt;p&gt;Each of these digits is created from the sum of its component bits. As a result, specific bits add to the sum as it is represented by a numeral:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;em&gt;read&lt;/em&gt; bit adds 4 to its total (in binary &lt;code&gt;100&lt;/code&gt;),&lt;/li&gt;
&lt;li&gt;The &lt;em&gt;write&lt;/em&gt; bit adds 2 to its total (in binary &lt;code&gt;010&lt;/code&gt;), and&lt;/li&gt;
&lt;li&gt;The &lt;em&gt;execute&lt;/em&gt; bit adds 1 to its total (in binary &lt;code&gt;001&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These values never produce ambiguous combinations and therefore each sum represents a unique set of permissions. Let's take &lt;code&gt;600&lt;/code&gt; as an example. The first digit &lt;code&gt;6&lt;/code&gt; represents the permissions for the owner. In binary it is &lt;code&gt;110&lt;/code&gt; and the only way to create it is from the sum of component bits above by adding &lt;code&gt;010&lt;/code&gt; (&lt;em&gt;write&lt;/em&gt; access) to &lt;code&gt;100&lt;/code&gt; (&lt;em&gt;read&lt;/em&gt; access). In other words, the owner has permission to read and write the file, but not to execute it.&lt;/p&gt;

&lt;p&gt;Using this system for permissions is optimized for data storage. But also turning permissions on (or off) can be done efficiently in what is known as bit-masking.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bitmasks
&lt;/h2&gt;

&lt;p&gt;You see, to turn certain bits on, the &lt;code&gt;OR&lt;/code&gt; operator can be used. This operator follows the rule that &lt;code&gt;X OR 1 = 1&lt;/code&gt; and &lt;code&gt;X OR 0 = X&lt;/code&gt;. If from the example above we now also want the owner to have &lt;em&gt;executive&lt;/em&gt; permission on the file, we simply use &lt;code&gt;OR&lt;/code&gt; with 1 (&lt;em&gt;execute&lt;/em&gt; value) on the current permission value: &lt;code&gt;6 OR 1 = 7&lt;/code&gt;, or in binary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   110
OR
   001
=  111
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can also turn off certain bits by using the &lt;code&gt;AND&lt;/code&gt; operator, which follows the rule that &lt;code&gt;X AND 1 = X&lt;/code&gt; and &lt;code&gt;X AND 0 = 0&lt;/code&gt;. To turn off a bit we use it with &lt;code&gt;0&lt;/code&gt;. Interestingly we can leave the bit as it was when using &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Turning bits on and off is also referred to as "masking on" and "masking off".&lt;/p&gt;

&lt;p&gt;Using this very old technique to store permission parts is very cool! But are there other use-cases where it makes sense? There are still today a ton of them, although they have become unpopular due to much more efficient hardware allowing the use of a set or dictionary to store the representations that a bit would otherwise hold.&lt;/p&gt;

&lt;h2&gt;
  
  
  Filtering using bit masking
&lt;/h2&gt;

&lt;p&gt;For the &lt;a href="https://github.com/ofek/bit"&gt;Bit&lt;/a&gt; project I needed a way to store the supported features for each of the numerous objects representing network APIs. Instead of using a dictionary to map each API to its supported set of features, or store a set of features on each API, I chose to use a system similar to the Unix access permission values.&lt;/p&gt;

&lt;p&gt;Making use of bit masking allows for fast filtering of APIs depending on specific features. This can be achieved by using a single &lt;code&gt;AND&lt;/code&gt; operator. We just use a filter value &lt;code&gt;Y&lt;/code&gt; that represents the features we want to filter for, and the value &lt;code&gt;X&lt;/code&gt; representing the supported features of some API object. Calculating &lt;code&gt;X AND Y&lt;/code&gt; gives another value &lt;code&gt;Z&lt;/code&gt;. But recall that each bit in &lt;code&gt;Z&lt;/code&gt; will either be 0 if the bit in &lt;code&gt;Y&lt;/code&gt; was 0, or it will be the bit of &lt;code&gt;X&lt;/code&gt; itself.&lt;/p&gt;

&lt;p&gt;Can you see the subtle implication from this? If the n'th bit of our filtering value &lt;code&gt;Y&lt;/code&gt; was 0 then the n'th bit of the result &lt;code&gt;Z&lt;/code&gt; will be 0. There is no loss of information because we didn't care if the bit value in &lt;code&gt;X&lt;/code&gt; signaled support for this feature or not. But if the n'th bit of &lt;code&gt;Y&lt;/code&gt; was 1 then we also want the n'th bit of &lt;code&gt;Z&lt;/code&gt; to be 1. This is only possible if the corresponding bit in &lt;code&gt;X&lt;/code&gt; was 1, hence signaling support for this feature. We can thus compare the result &lt;code&gt;Z&lt;/code&gt; to &lt;code&gt;Y&lt;/code&gt; itself. If &lt;code&gt;X AND Y == Y&lt;/code&gt;, then and only then will the value of &lt;code&gt;X&lt;/code&gt; signal for (at least) all the features we are filtering for with the value &lt;code&gt;Y&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's take a quick example using Unix permission values again. Let's say we have a list of files with permission values and want to filter them to keep only those that we are allowed to &lt;em&gt;read&lt;/em&gt;, which is the value 4 or in binary &lt;code&gt;100&lt;/code&gt;. One of the files may have a permission value of 5, which in binary is &lt;code&gt;101&lt;/code&gt; and thus corresponds to &lt;em&gt;read&lt;/em&gt; and &lt;em&gt;execute&lt;/em&gt; permission.&lt;/p&gt;

&lt;p&gt;A filter to see if at least the &lt;em&gt;read&lt;/em&gt; permission was set on this file would be checked as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    101
AND
    100
=   100
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We see that the result on the last line is exactly the same value as our filter. This is just as we expected and we would therefore keep it.&lt;/p&gt;

&lt;p&gt;If a file gives us permission to &lt;em&gt;write&lt;/em&gt; and &lt;em&gt;execute&lt;/em&gt;, but not to &lt;em&gt;read&lt;/em&gt;, it is represented as a 3 or in binary &lt;code&gt;011&lt;/code&gt;. Applying our filter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    011
AND
    100
=   000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The result is different from our filter and we therefore immediately know that the filter was not satisfied.&lt;/p&gt;

&lt;p&gt;The real beauty comes from applying complex filters with multiple bits turned on. If we would want to filter for e.g. &lt;em&gt;read&lt;/em&gt; and &lt;em&gt;execute&lt;/em&gt; permissions, the filter would be &lt;code&gt;101&lt;/code&gt; and just as before we would check if the final &lt;code&gt;AND&lt;/code&gt; result would equal this value.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The value &lt;code&gt;Z&lt;/code&gt; resulting from using the &lt;code&gt;AND&lt;/code&gt; operator on a file's permission and filter value is the &lt;em&gt;intersection&lt;/em&gt; of the permissions in the file and the filter.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Bitmask filtering in Python
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Using Python 3.6+
&lt;/h3&gt;

&lt;p&gt;Since Python 3.6 a class &lt;code&gt;Flag&lt;/code&gt; exists for bit mask operations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;enum&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;IntFlag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;auto&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Permissions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IntFlag&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;    &lt;span class="n"&gt;EXECUTE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;    &lt;span class="n"&gt;WRITE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;    &lt;span class="n"&gt;READ&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PermissionSet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_permission&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Permissions&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="c1"&gt;# Initiate no permissions
&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_permission&lt;/span&gt; &lt;span class="o"&gt;|=&lt;/span&gt; &lt;span class="n"&gt;Permissions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__contains__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_permission&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_permission&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_permission&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can use this &lt;code&gt;PermissionSet&lt;/code&gt; class to store the permissions of a file as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;permission&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_permissions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PermissionSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;permission&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's use it in action!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# A filter:
&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;permission_filter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PermissionSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"read"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"execute"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# The dummy files:
&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"file_rw"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;permission&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"read"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"write"&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;              &lt;span class="c1"&gt;# Should be excluded from filter
&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"file_re"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;permission&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"read"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"execute"&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;            &lt;span class="c1"&gt;# Should be included from filter
&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"file_w"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;permission&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"read"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"execute"&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;             &lt;span class="c1"&gt;# Should be included from filter
&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"file_we"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;permission&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"write"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"execute"&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;           &lt;span class="c1"&gt;# Should be excluded from filter
&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"file_rwe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;permission&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"read"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"write"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"execute"&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;  &lt;span class="c1"&gt;# Should be included from filter
&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# Filter the files:
&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;permission_filter&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_permissions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="s"&gt;'file_re'&lt;/span&gt;
&lt;span class="s"&gt;'file_w'&lt;/span&gt;
&lt;span class="s"&gt;'file_rwe'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Using Python 3.5
&lt;/h3&gt;

&lt;p&gt;However, also before Python 3.6 this could be achieved using the &lt;code&gt;IntEnum&lt;/code&gt; class, however with manual adjustment of the underlying permission values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;enum&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;IntEnum&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Permissions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IntEnum&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;    &lt;span class="n"&gt;EXECUTE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;    &lt;span class="n"&gt;WRITE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;    &lt;span class="n"&gt;READ&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PermissionSet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_permission&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;  &lt;span class="c1"&gt;# Initiate no permissions
&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_permission&lt;/span&gt; &lt;span class="o"&gt;|=&lt;/span&gt; &lt;span class="n"&gt;Permissions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__contains__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_permission&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_permission&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_permission&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can then use it in the exact same way we already did above in the example for &lt;code&gt;IntFlag&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What do you think about this technique? Is it elegant? Or over-engineering?&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>binary</category>
      <category>bitmask</category>
    </item>
    <item>
      <title>Making a Blog With Hugo And Netlify</title>
      <dc:creator>Bjarne Magnussen</dc:creator>
      <pubDate>Mon, 02 Sep 2019 21:41:50 +0000</pubDate>
      <link>https://dev.to/bjarnemagnussen/making-a-blog-with-hugo-and-netlify-f3l</link>
      <guid>https://dev.to/bjarnemagnussen/making-a-blog-with-hugo-and-netlify-f3l</guid>
      <description>&lt;p&gt;Numerous blog posts already exist to explain how to build a blog with Hugo and deploy it using Netlify. But since this is my first blog post (a warm welcome by the way ❤️) I wanted to briefly describe how I created my own site, which you can find on &lt;a href="https://bjarnemagnussen.netlify.com"&gt;https://bjarnemagnussen.netlify.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I will also clarify things I have often found lacking in other descriptions, such as what to be aware of when using Netlify, how to use a &lt;em&gt;private&lt;/em&gt; repository for the raw files and how to use the Academic theme of Hugo. Some prior knowledge of git and GitHub is required.&lt;/p&gt;

&lt;p&gt;When I started out to create my own site I wanted something that was &lt;strong&gt;easy to deploy&lt;/strong&gt; and with support for &lt;strong&gt;markdown&lt;/strong&gt;. It is my preferred way to write and the choice quickly went for &lt;strong&gt;a static site generator&lt;/strong&gt;. I chose &lt;em&gt;Hugo&lt;/em&gt; because it is written in Go (the language I currently study) and I liked the look of the Academic theme. Easy deployment with Netlify was also a clear plus.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Hugo With Academic Theme
&lt;/h2&gt;

&lt;p&gt;I chose an installation method that uses git and GitHub as described &lt;a href="https://sourcethemes.com/academic/docs/install#install-with-git"&gt;here&lt;/a&gt;. However, &lt;strong&gt;I didn't want my raw markdown documents and configuration files exposed in a public repository&lt;/strong&gt; and changed some steps in the installation process.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;First create a &lt;strong&gt;private&lt;/strong&gt; repository on GitHub, you can name it whatever you want.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then clone the &lt;code&gt;academic-kickstart&lt;/code&gt; repository to your local machine in a temporary dictionary &lt;em&gt;mirror&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;mirror
&lt;span class="nb"&gt;cd &lt;/span&gt;mirror
git clone &lt;span class="nt"&gt;--bare&lt;/span&gt; https://github.com/sourcethemes/academic-kickstart.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Finally push it to your private repository created in step 1 (change &lt;code&gt;yourname&lt;/code&gt; and &lt;code&gt;private-repo&lt;/code&gt; accordingly below).
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;academic-kickstart.git
git push &lt;span class="nt"&gt;--mirror&lt;/span&gt; https://github.com/yourname/private-repo.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You now have a basic Academic theme skeleton inside your repository and can delete the temporary &lt;em&gt;mirror&lt;/em&gt; folder that was only created for this purpose.&lt;/p&gt;

&lt;p&gt;Use your repository in any of the usual ways you find convenient. Academic comes pre-installed with many example pages and configuration options. You can find the documentation page for it &lt;a href="https://sourcethemes.com/academic/docs/"&gt;here&lt;/a&gt; and change the example files according to your taste and need.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying The Site
&lt;/h2&gt;

&lt;p&gt;To deploy the webpage on Netlify you will first have to register with them &lt;a href="https://netlify.com"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It is completely fine to register using only your email 😉. No need for GitHub's single-sign-on at this point!&lt;sup id="fnref1"&gt;1&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We can then deploy a new site by pressing the little "New site from Git" button in the top right.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--N1d1r3jx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://bjarnemagnussen.netlify.com/img/post/making-a-blog-with-hugo-and-netlify/screen1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--N1d1r3jx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://bjarnemagnussen.netlify.com/img/post/making-a-blog-with-hugo-and-netlify/screen1.png" alt="new-site-from-git"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the new window we select the "Github" option under "Continuous Deployment".&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2M08NYkM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://bjarnemagnussen.netlify.com/img/post/making-a-blog-with-hugo-and-netlify/screen2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2M08NYkM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://bjarnemagnussen.netlify.com/img/post/making-a-blog-with-hugo-and-netlify/screen2.png" alt="continuous-deployment-using-github"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We must then grand Netlify some rights and access to our private repository that we have specifically created for this purpose.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RYHVWNxG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://bjarnemagnussen.netlify.com/img/post/making-a-blog-with-hugo-and-netlify/screen3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RYHVWNxG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://bjarnemagnussen.netlify.com/img/post/making-a-blog-with-hugo-and-netlify/screen3.png" alt="select-repository"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Confirm it by clicking on the repository from within Netlify's window.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Neof3lrT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://bjarnemagnussen.netlify.com/img/post/making-a-blog-with-hugo-and-netlify/screen4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Neof3lrT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://bjarnemagnussen.netlify.com/img/post/making-a-blog-with-hugo-and-netlify/screen4.png" alt="confirm-repository"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And press the "Deploy site" button to deploy using default parameters for &lt;code&gt;hugo&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eXvxQoBU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://bjarnemagnussen.netlify.com/img/post/making-a-blog-with-hugo-and-netlify/screen5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eXvxQoBU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://bjarnemagnussen.netlify.com/img/post/making-a-blog-with-hugo-and-netlify/screen5.png" alt="confirm-default-parameters"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🎉 Congratulations! Your blog should show up under "Sites" and &lt;strong&gt;every&lt;/strong&gt; new commit to your private repository is automatically deployed.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X-eF8MTj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://bjarnemagnussen.netlify.com/img/post/making-a-blog-with-hugo-and-netlify/screen6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X-eF8MTj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://bjarnemagnussen.netlify.com/img/post/making-a-blog-with-hugo-and-netlify/screen6.png" alt="deployed-site"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You can now change the settings for "the-complicated-looking-and-automatically-assigned" subdomain, or switch to using your own domain name. All of that is explained on their &lt;a href="https://www.netlify.com/docs/custom-domains/"&gt;documentation page&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;Although we must link our GitHub account with Netlify, I always avoid using single-sign-ons from specific vendors. I find it disturbing to use as it complicates parting with the vendors later if we should not use their services anymore... ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>netlify</category>
      <category>hugo</category>
    </item>
  </channel>
</rss>
