@@ -19,6 +19,7 @@ Strings and Runes
|
||||
Structs
|
||||
Methods
|
||||
Interfaces
|
||||
Enums
|
||||
Struct Embedding
|
||||
Generics
|
||||
Errors
|
||||
|
75
examples/enums/enums.go
Normal file
75
examples/enums/enums.go
Normal file
@@ -0,0 +1,75 @@
|
||||
// _Enumerated types_ (enums) are a special case of
|
||||
// [sum types](https://en.wikipedia.org/wiki/Algebraic_data_type).
|
||||
// An enum is a type that has a fixed number of possible
|
||||
// values, each with a distinct name. Go doesn't have an
|
||||
// enum type as a distinct language feature, but enums
|
||||
// are simple to implement using existing language idioms.
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Our enum type `ServerState` has an underlying `int` type.
|
||||
type ServerState int
|
||||
|
||||
// The possible values for `ServerState` are defined as
|
||||
// constants. The special keyword [iota](https://go.dev/ref/spec#Iota)
|
||||
// generates successive constant values automatically; in this
|
||||
// case 0, 1, 2 and so on.
|
||||
const (
|
||||
StateIdle = iota
|
||||
StateConnected
|
||||
StateError
|
||||
StateRetrying
|
||||
)
|
||||
|
||||
// By implementing the [fmt.Stringer](https://pkg.go.dev/fmt#Stringer)
|
||||
// interface, values of `StateType` can be printed out or converted
|
||||
// to strings.
|
||||
//
|
||||
// This can get cumbersome if there are many possible values. In such
|
||||
// cases the [stringer tool](https://pkg.go.dev/golang.org/x/tools/cmd/stringer)
|
||||
// can be used in conjunction with `go:generate` to automate the
|
||||
// process. See [this post](https://eli.thegreenplace.net/2021/a-comprehensive-guide-to-go-generate)
|
||||
// for a longer explanation.
|
||||
var stateName = map[ServerState]string{
|
||||
StateIdle: "idle",
|
||||
StateConnected: "connected",
|
||||
StateError: "error",
|
||||
StateRetrying: "retrying",
|
||||
}
|
||||
|
||||
func (ss ServerState) String() string {
|
||||
return stateName[ss]
|
||||
}
|
||||
|
||||
func main() {
|
||||
ns := transition(StateIdle)
|
||||
fmt.Println(ns)
|
||||
// If we have a value of type `int`, we cannot pass it to `transition` - the
|
||||
// compiler will complain about type mismatch. This provides some degree of
|
||||
// compile-time type safety for enums.
|
||||
|
||||
ns2 := transition(ns)
|
||||
fmt.Println(ns2)
|
||||
}
|
||||
|
||||
// transition emulates a state transition for a
|
||||
// server; it takes the existing state and returns
|
||||
// a new state.
|
||||
func transition(s ServerState) ServerState {
|
||||
switch s {
|
||||
case StateIdle:
|
||||
return StateConnected
|
||||
case StateConnected, StateRetrying:
|
||||
// Suppose we check some predicates here to
|
||||
// determine the next state...
|
||||
return StateIdle
|
||||
case StateError:
|
||||
return StateError
|
||||
default:
|
||||
panic(fmt.Errorf("unwknown state: %s", s))
|
||||
}
|
||||
|
||||
return StateConnected
|
||||
}
|
2
examples/enums/enums.hash
Normal file
2
examples/enums/enums.hash
Normal file
@@ -0,0 +1,2 @@
|
||||
1c5bf51fa651a25eb6d9d2d24cf7dbd2713aca0c
|
||||
-6dSwyy83xj
|
3
examples/enums/enums.sh
Normal file
3
examples/enums/enums.sh
Normal file
@@ -0,0 +1,3 @@
|
||||
$ go run enums.go
|
||||
connected
|
||||
idle
|
240
public/enums
generated
Normal file
240
public/enums
generated
Normal file
@@ -0,0 +1,240 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Go by Example: Enums</title>
|
||||
<link rel=stylesheet href="site.css">
|
||||
</head>
|
||||
<script>
|
||||
window.onkeydown = (e) => {
|
||||
if (e.ctrlKey || e.altKey || e.shiftKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.key == "ArrowLeft") {
|
||||
window.location.href = 'interfaces';
|
||||
}
|
||||
|
||||
|
||||
if (e.key == "ArrowRight") {
|
||||
window.location.href = 'struct-embedding';
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
<body>
|
||||
<div class="example" id="enums">
|
||||
<h2><a href="./">Go by Example</a>: Enums</h2>
|
||||
|
||||
<table>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p><em>Enumerated types</em> (enums) are a special case of
|
||||
<a href="https://en.wikipedia.org/wiki/Algebraic_data_type">sum types</a>.
|
||||
An enum is a type that has a fixed number of possible
|
||||
values, each with a distinct name. Go doesn’t have an
|
||||
enum type as a distinct language feature, but enums
|
||||
are simple to implement using existing language idioms.</p>
|
||||
|
||||
</td>
|
||||
<td class="code empty leading">
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
<a href="https://go.dev/play/p/-6dSwyy83xj"><img title="Run code" src="play.png" class="run" /></a><img title="Copy code" src="clipboard.png" class="copy" />
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main</span></span></span></code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">import</span> <span class="s">"fmt"</span></span></span></code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>Our enum type <code>ServerState</code> has an underlying <code>int</code> type.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">ServerState</span> <span class="kt">int</span></span></span></code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>The possible values for <code>ServerState</code> are defined as
|
||||
constants. The special keyword <a href="https://go.dev/ref/spec#Iota">iota</a>
|
||||
generates successive constant values automatically; in this
|
||||
case 0, 1, 2 and so on.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"><span class="kd">const</span> <span class="p">(</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="nx">StateIdle</span> <span class="p">=</span> <span class="kc">iota</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="nx">StateConnected</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="nx">StateError</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="nx">StateRetrying</span>
|
||||
</span></span><span class="line"><span class="cl"><span class="p">)</span></span></span></code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>By implementing the <a href="https://pkg.go.dev/fmt#Stringer">fmt.Stringer</a>
|
||||
interface, values of <code>StateType</code> can be printed out or converted
|
||||
to strings.</p>
|
||||
|
||||
<p>This can get cumbersome if there are many possible values. In such
|
||||
cases the <a href="https://pkg.go.dev/golang.org/x/tools/cmd/stringer">stringer tool</a>
|
||||
can be used in conjunction with <code>go:generate</code> to automate the
|
||||
process. See <a href="https://eli.thegreenplace.net/2021/a-comprehensive-guide-to-go-generate">this post</a>
|
||||
for a longer explanation.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">stateName</span> <span class="p">=</span> <span class="kd">map</span><span class="p">[</span><span class="nx">ServerState</span><span class="p">]</span><span class="kt">string</span><span class="p">{</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="nx">StateIdle</span><span class="p">:</span> <span class="s">"idle"</span><span class="p">,</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="nx">StateConnected</span><span class="p">:</span> <span class="s">"connected"</span><span class="p">,</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="nx">StateError</span><span class="p">:</span> <span class="s">"error"</span><span class="p">,</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="nx">StateRetrying</span><span class="p">:</span> <span class="s">"retrying"</span><span class="p">,</span>
|
||||
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"><span class="kd">func</span> <span class="p">(</span><span class="nx">ss</span> <span class="nx">ServerState</span><span class="p">)</span> <span class="nf">String</span><span class="p">()</span> <span class="kt">string</span> <span class="p">{</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">stateName</span><span class="p">[</span><span class="nx">ss</span><span class="p">]</span>
|
||||
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>If we have a value of type <code>int</code>, we cannot pass it to <code>transition</code> - the
|
||||
compiler will complain about type mismatch. This provides some degree of
|
||||
compile-time type safety for enums.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="nx">ns</span> <span class="o">:=</span> <span class="nf">transition</span><span class="p">(</span><span class="nx">StateIdle</span><span class="p">)</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">ns</span><span class="p">)</span></span></span></code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"> <span class="nx">ns2</span> <span class="o">:=</span> <span class="nf">transition</span><span class="p">(</span><span class="nx">ns</span><span class="p">)</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">ns2</span><span class="p">)</span>
|
||||
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>transition emulates a state transition for a
|
||||
server; it takes the existing state and returns
|
||||
a new state.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">transition</span><span class="p">(</span><span class="nx">s</span> <span class="nx">ServerState</span><span class="p">)</span> <span class="nx">ServerState</span> <span class="p">{</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="k">switch</span> <span class="nx">s</span> <span class="p">{</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="nx">StateIdle</span><span class="p">:</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">StateConnected</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="nx">StateConnected</span><span class="p">,</span> <span class="nx">StateRetrying</span><span class="p">:</span></span></span></code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>Suppose we check some predicates here to
|
||||
determine the next state…</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">StateIdle</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="nx">StateError</span><span class="p">:</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">StateError</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="k">default</span><span class="p">:</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="nb">panic</span><span class="p">(</span><span class="nx">fmt</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">"unwknown state: %s"</span><span class="p">,</span> <span class="nx">s</span><span class="p">))</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="p">}</span></span></span></code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
|
||||
</td>
|
||||
<td class="code">
|
||||
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">StateConnected</span>
|
||||
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
<table>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
|
||||
</td>
|
||||
<td class="code">
|
||||
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"><span class="gp">$</span> go run enums.go
|
||||
</span></span><span class="line"><span class="cl"><span class="go">connected
|
||||
</span></span></span><span class="line"><span class="cl"><span class="go">idle</span></span></span></code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
<p class="next">
|
||||
Next example: <a href="struct-embedding">Struct Embedding</a>.
|
||||
</p>
|
||||
|
||||
|
||||
<p class="footer">
|
||||
by <a href="https://markmcgranaghan.com">Mark McGranaghan</a> and <a href="https://eli.thegreenplace.net">Eli Bendersky</a> | <a href="https://github.com/mmcgrana/gobyexample">source</a> | <a href="https://github.com/mmcgrana/gobyexample#license">license</a>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
<script>
|
||||
var codeLines = [];
|
||||
codeLines.push('');codeLines.push('package main\u000A');codeLines.push('import \"fmt\"\u000A');codeLines.push('type ServerState int\u000A');codeLines.push('const (\u000A StateIdle \u003D iota\u000A StateConnected\u000A StateError\u000A StateRetrying\u000A)\u000A');codeLines.push('var stateName \u003D map[ServerState]string{\u000A StateIdle: \"idle\",\u000A StateConnected: \"connected\",\u000A StateError: \"error\",\u000A StateRetrying: \"retrying\",\u000A}\u000A');codeLines.push('func (ss ServerState) String() string {\u000A return stateName[ss]\u000A}\u000A');codeLines.push('func main() {\u000A ns :\u003D transition(StateIdle)\u000A fmt.Println(ns)\u000A');codeLines.push(' ns2 :\u003D transition(ns)\u000A fmt.Println(ns2)\u000A}\u000A');codeLines.push('func transition(s ServerState) ServerState {\u000A switch s {\u000A case StateIdle:\u000A return StateConnected\u000A case StateConnected, StateRetrying:\u000A');codeLines.push(' return StateIdle\u000A case StateError:\u000A return StateError\u000A default:\u000A panic(fmt.Errorf(\"unwknown state: %s\", s))\u000A }\u000A');codeLines.push(' return StateConnected\u000A}\u000A');codeLines.push('');
|
||||
</script>
|
||||
<script src="site.js" async></script>
|
||||
</body>
|
||||
</html>
|
2
public/index.html
generated
2
public/index.html
generated
@@ -69,6 +69,8 @@
|
||||
|
||||
<li><a href="interfaces">Interfaces</a></li>
|
||||
|
||||
<li><a href="enums">Enums</a></li>
|
||||
|
||||
<li><a href="struct-embedding">Struct Embedding</a></li>
|
||||
|
||||
<li><a href="generics">Generics</a></li>
|
||||
|
4
public/interfaces
generated
4
public/interfaces
generated
@@ -17,7 +17,7 @@
|
||||
|
||||
|
||||
if (e.key == "ArrowRight") {
|
||||
window.location.href = 'struct-embedding';
|
||||
window.location.href = 'enums';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -210,7 +210,7 @@ these structs as arguments to <code>measure</code>.</p>
|
||||
|
||||
|
||||
<p class="next">
|
||||
Next example: <a href="struct-embedding">Struct Embedding</a>.
|
||||
Next example: <a href="enums">Enums</a>.
|
||||
</p>
|
||||
|
||||
|
||||
|
2
public/struct-embedding
generated
2
public/struct-embedding
generated
@@ -12,7 +12,7 @@
|
||||
}
|
||||
|
||||
if (e.key == "ArrowLeft") {
|
||||
window.location.href = 'interfaces';
|
||||
window.location.href = 'enums';
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user