<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.2">Jekyll</generator><link href="https://mchirico.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://mchirico.github.io/" rel="alternate" type="text/html" /><updated>2022-11-06T13:21:18+00:00</updated><id>https://mchirico.github.io/feed.xml</id><title type="html">Mike Chirico</title><subtitle>Go (Golang), Kubernetes, AWS, Argo Workflows, iOS/Swift development... that sort of thing.
</subtitle><author><name>Mike Chirico</name><email>mchirico@gmail.com</email></author><entry><title type="html">Bytes Buffer in Go</title><link href="https://mchirico.github.io/python/2022/10/24/bytesBuffer.html" rel="alternate" type="text/html" title="Bytes Buffer in Go" /><published>2022-10-24T23:38:50+00:00</published><updated>2022-10-24T23:38:50+00:00</updated><id>https://mchirico.github.io/python/2022/10/24/bytesBuffer</id><content type="html" xml:base="https://mchirico.github.io/python/2022/10/24/bytesBuffer.html">&lt;p&gt;Strings in Go are extremely inefficient. They are immutable and are stored as a slice of bytes. This means that every time you want to append a character to a string, you have to create a new string and copy the old one into it. This is extremely inefficient and can lead to a lot of memory usage.&lt;/p&gt;

&lt;p&gt;It’s better to use bytes buffer instead of strings. Bytes buffer is a mutable slice of bytes. It is more efficient than strings because it doesn’t have to create a new string every time you want to append a character to it. It can just append the character to the end of the slice.&lt;/p&gt;

&lt;p&gt;Here is an example of how to use bytes buffer:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-go&quot;&gt;    package main

    import (
        &quot;bytes&quot;
        &quot;fmt&quot;
    )

    func main() {
        var buffer bytes.Buffer
        buffer.WriteString(&quot;Hello&quot;)
        buffer.WriteString(&quot; &quot;)
        buffer.WriteString(&quot;World&quot;)
        fmt.Println(buffer.String())
        // Note: We don't clear buffer
        fmt.Println(&quot;We didn't clear buffer. Len: &quot;,buffer.Len()) 
    }

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://go.dev/play/p/eYaUNqNKI0G&quot;&gt;playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Above we didn’t clear the buffer.  Below we create our own Read, and 
read in nBytes each pass through the loop, until io.EOF.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-go&quot;&gt;package main

import (
	&quot;bytes&quot;
	&quot;fmt&quot;
	&quot;io&quot;
)

func Read(r io.Reader, nBytes int) {
	for {
		b := make([]byte, nBytes)
		n, err := r.Read(b)
		if err != nil {
			fmt.Printf(&quot;Done: %d,b: %s\n&quot;, n, string(b))
			if err == io.EOF {
				return
			}
			fmt.Println(&quot;error: &quot;, err)
		}
		fmt.Printf(&quot;%d,b: %s\n&quot;, n, string(b))
	}
}

func main() {
	var buf bytes.Buffer
	nBytes := 5
	buf.WriteString(&quot;This is a string here.&quot;)
	buf.WriteString(
        fmt.Sprintf(&quot; We will read %d bytes at a time.&quot;, nBytes))
	Read(&amp;amp;buf, nBytes)
	fmt.Println(buf.String())
	fmt.Println(buf.Len())

	fmt.Println(&quot;buf: &quot;, buf.String())
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://go.dev/play/p/zSS1q3xn6Vl&quot;&gt;playground&lt;/a&gt;&lt;/p&gt;</content><author><name>Mike Chirico</name><email>mchirico@gmail.com</email></author><category term="python" /><summary type="html">Strings in Go are extremely inefficient. They are immutable and are stored as a slice of bytes. This means that every time you want to append a character to a string, you have to create a new string and copy the old one into it. This is extremely inefficient and can lead to a lot of memory usage.</summary></entry><entry><title type="html">AWS Sessions</title><link href="https://mchirico.github.io/aws/2022/10/23/AWS_tmp.html" rel="alternate" type="text/html" title="AWS Sessions" /><published>2022-10-23T14:32:49+00:00</published><updated>2022-10-23T14:32:49+00:00</updated><id>https://mchirico.github.io/aws/2022/10/23/AWS_tmp</id><content type="html" xml:base="https://mchirico.github.io/aws/2022/10/23/AWS_tmp.html">&lt;p&gt;Simple way to generate and jump into a new AWS temp session. 
The session here expires after 15 minutes.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;#!/bin/bash
set -e

sts=( $(
    aws sts get-session-token --duration-seconds 900  \
    --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]' \
    --output text
) )
export TMP_AWS_ACCESS_KEY_ID=${sts[0]}
export TMP_AWS_SECRET_ACCESS_KEY=${sts[1]}
export TMP_AWS_SESSION_TOKEN=${sts[2]}

&lt;/code&gt;&lt;/pre&gt;</content><author><name>Mike Chirico</name><email>mchirico@gmail.com</email></author><category term="aws" /><summary type="html">Simple way to generate and jump into a new AWS temp session. The session here expires after 15 minutes.</summary></entry><entry><title type="html">Go Custom Errors</title><link href="https://mchirico.github.io/go/2022/10/23/errors.html" rel="alternate" type="text/html" title="Go Custom Errors" /><published>2022-10-23T13:53:06+00:00</published><updated>2022-10-23T13:53:06+00:00</updated><id>https://mchirico.github.io/go/2022/10/23/errors</id><content type="html" xml:base="https://mchirico.github.io/go/2022/10/23/errors.html">&lt;pre&gt;&lt;code class=&quot;language-go&quot;&gt;package main

import (
	&quot;errors&quot;
	&quot;fmt&quot;
)

// FooError records an error and what caused it
type FooError struct {
	Op       string
	FooThing string
	Err      error
}

// ErrorCreator creates an error, which is an interface, so we can return *FooError as error

//	   type error interface {
//		       Error() string
//	    }
func ErrorCreator() error {
	return &amp;amp;FooError{
		Op:       &quot;was eating miso soup&quot;,
		FooThing: &quot;just happend&quot;,
		Err:      errors.New(&quot;bad fortune cookie&quot;),
	}

}

func (e *FooError) Error() string { return e.Op + &quot; &quot; + e.FooThing + &quot;: &quot; + e.Err.Error() }

func (e *FooError) Unwrap() error { return e.Err }

func (e *FooError) Thing() string { return e.FooThing }

// The key here is to use &quot;errors.As&quot; to check if the error is of type FooError
func main() {
	if err := ErrorCreator(); err != nil {
		var fooError *FooError
		if errors.As(err, &amp;amp;fooError) {
			fmt.Println(&quot;Explain failure thing...:&quot;, fooError.Thing())
		} else {
			fmt.Println(err)
		}
	}

}

&lt;/code&gt;&lt;/pre&gt;</content><author><name>Mike Chirico</name><email>mchirico@gmail.com</email></author><category term="Go" /><summary type="html">```go package main</summary></entry><entry><title type="html">AWS ECT with Kubernetes KinD</title><link href="https://mchirico.github.io/aws/2022/09/22/aws-ecr-k8s.html" rel="alternate" type="text/html" title="AWS ECT with Kubernetes KinD" /><published>2022-09-22T19:18:33+00:00</published><updated>2022-09-22T19:18:33+00:00</updated><id>https://mchirico.github.io/aws/2022/09/22/aws-ecr-k8s</id><content type="html" xml:base="https://mchirico.github.io/aws/2022/09/22/aws-ecr-k8s.html">&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;

TOKEN=$(aws ecr get-login-password --region us-east-1)
SERVER=$(aws ecr describe-repositories|jq '.repositories[0].repositoryUri'|sed  's/\/.*//'|sed -r 's/\&quot;//g')
NAMESPACE=&quot;dev&quot;


kubectl create namespace $NAMESPACE
kubectl create secret docker-registry regcred \
--docker-server=${SERVER} \
--docker-username=AWS --docker-password=${TOKEN} -n ${NAMESPACE}

kubectl patch serviceaccount default -p &quot;{\&quot;imagePullSecrets\&quot;: [{\&quot;name\&quot;: \&quot;regcred\&quot;}]}&quot; -n ${NAMESPACE}



&lt;/code&gt;&lt;/pre&gt;

&lt;h1 id=&quot;try-pulling-image&quot;&gt;Try pulling image&lt;/h1&gt;

&lt;p&gt;Note, you’ll need to replace &lt;code&gt;1111.xxx.ecr.us-east-1.amazonaws.com/repodev:latest&lt;/code&gt; with your own image.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl create deployment --image=1111.xxx.ecr.us-east-1.amazonaws.com/repodev:latest dev-dep

&lt;/code&gt;&lt;/pre&gt;</content><author><name>Mike Chirico</name><email>mchirico@gmail.com</email></author><category term="AWS" /><summary type="html">```bash</summary></entry><entry><title type="html">Go Relative Directory</title><link href="https://mchirico.github.io/go/2022/08/29/relDir.html" rel="alternate" type="text/html" title="Go Relative Directory" /><published>2022-08-29T14:28:53+00:00</published><updated>2022-08-29T14:28:53+00:00</updated><id>https://mchirico.github.io/go/2022/08/29/relDir</id><content type="html" xml:base="https://mchirico.github.io/go/2022/08/29/relDir.html">&lt;pre&gt;&lt;code class=&quot;language-Go&quot;&gt;package fixtures

import (
	&quot;path/filepath&quot;
	&quot;runtime&quot;
)

// basepath is the root directory of this package.
var basepath string

func init() {
	_, currentFile, _, _ := runtime.Caller(0)
	basepath = filepath.Dir(currentFile)
}

// Path returns the absolute path the given relative file or directory path,
// relative to the &quot;fixtures&quot; directory.
// If rel is already absolute, it is returned unmodified.
func Path(rel string) string {
	if filepath.IsAbs(rel) {
		return rel
	}

	return filepath.Join(basepath, rel)
}


&lt;/code&gt;&lt;/pre&gt;</content><author><name>Mike Chirico</name><email>mchirico@gmail.com</email></author><category term="Go" /><summary type="html">```Go package fixtures</summary></entry><entry><title type="html">Go Embedding</title><link href="https://mchirico.github.io/go/2022/08/07/embedding.html" rel="alternate" type="text/html" title="Go Embedding" /><published>2022-08-07T18:43:52+00:00</published><updated>2022-08-07T18:43:52+00:00</updated><id>https://mchirico.github.io/go/2022/08/07/embedding</id><content type="html" xml:base="https://mchirico.github.io/go/2022/08/07/embedding.html">&lt;p&gt;Example using embeddings… with interface
&lt;a href=&quot;https://go.dev/play/p/7HHEbxlQt4T&quot;&gt;playground&lt;/a&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-go&quot;&gt;package main

import (
	&quot;fmt&quot;
)

type A struct{}

func (a *A) f0() string {
	return &quot;f0()&quot;
}

type B struct{}

func (b *B) f1() string {
	return &quot;f1()&quot;
}

type f0f1 interface {
	f0() string
	f1() string
}

type C struct {
	*A
	*B
}

func Pr(f f0f1) {
	fmt.Println(f.f0())
	fmt.Println(f.f1())

}

func main() {
	c := &amp;amp;C{A: &amp;amp;A{}, B: &amp;amp;B{}}
	Pr(c)

}
&lt;/code&gt;&lt;/pre&gt;</content><author><name>Mike Chirico</name><email>mchirico@gmail.com</email></author><category term="Go" /><summary type="html">Example using embeddings… with interface playground</summary></entry><entry><title type="html">Go Programs – Reminders</title><link href="https://mchirico.github.io/go/2022/06/28/golearnings.html" rel="alternate" type="text/html" title="Go Programs – Reminders" /><published>2022-06-28T14:10:53+00:00</published><updated>2022-06-28T14:10:53+00:00</updated><id>https://mchirico.github.io/go/2022/06/28/golearnings</id><content type="html" xml:base="https://mchirico.github.io/go/2022/06/28/golearnings.html">&lt;p&gt;Some personal reminders on Go development.&lt;/p&gt;

&lt;h2 id=&quot;1-perfect-is-enemy-of-good&quot;&gt;1) Perfect is enemy of good.&lt;/h2&gt;

&lt;p&gt;Often times is makes sense to keep going with a code idea. Write tests, so you can back out. 
But, if you have writers block… sometimes it helps to just code.  Other options:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Write next move with pen and paper - this helps with complex structures&lt;/li&gt;
  &lt;li&gt;Review previous works of code - always helps to read other’s code&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;2-interface-names-should-be-verbs&quot;&gt;2) Interface Names (should be verbs)&lt;/h2&gt;

&lt;p&gt;Use verbs for interface names.  Ref &lt;a href=&quot;https://github.com/golang/go/blob/master/src/io/io.go&quot;&gt;io.go&lt;/a&gt;, where
names are &lt;code&gt;WriteString, Reader, ByteWriter, Closer...&lt;/code&gt;  Interfaces define function calls, so should be actions.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-go&quot;&gt;type Reader interface {
	Read(p []byte) (n int, err error)
}
...
type Writer interface {
	Write(p []byte) (n int, err error)
}

type Closer interface {
	Close() error
}

&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;3-select--hate-this-about-go&quot;&gt;3) Select – Hate this about Go&lt;/h2&gt;

&lt;p&gt;The two programs below produce different results, based on where
the “{“ is placed in the select.&lt;/p&gt;

&lt;h3 id=&quot;always-false&quot;&gt;Always &lt;code&gt;false&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-go&quot;&gt;package main

func False() bool {
	return false
}

func main() {
	switch False() {
	case false: println(&quot;False&quot;)
	case true: println(&quot;True&quot;)
	}
}
// Returns false
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;a href=&quot;https://go.dev/play/p/9X9PmyGEOnM&quot;&gt;above program&lt;/a&gt; will always return false. It does what you expect it to do.&lt;/p&gt;

&lt;h3 id=&quot;always-true&quot;&gt;Always &lt;code&gt;true&lt;/code&gt;&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&quot;language-go&quot;&gt;package main

func False() bool {
	return false
}

func main() {
	switch False() // &amp;lt;&amp;lt;== Note &quot;{&quot; is no longer on this line
	{
	case false: println(&quot;False&quot;)
	case true: println(&quot;True&quot;)
	}
}
// returns true
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But, the above program returns &lt;code&gt;true&lt;/code&gt;, because it’s really
formatted to be the &lt;a href=&quot;https://go.dev/play/p/fmMPSm5OuEz&quot;&gt;following&lt;/a&gt;…&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-go&quot;&gt;package main

func False() bool {
	return false
}

func main() {
	switch False(); {
	case false:
		println(&quot;False&quot;)
	case true:
		println(&quot;True&quot;)
	}
}

&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;4---files-relative&quot;&gt;4 - Files relative&lt;/h3&gt;

&lt;p&gt;Reading files from relative directories doesn’t have to be
difficult. Package &lt;code&gt;runtime&lt;/code&gt; allows you to read in files
relative to what directory you code is running in…&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-go&quot;&gt;import (
	&quot;path/filepath&quot;
	&quot;runtime&quot;
)

var basepath string

func init() {
	_, currentFile, _, _ := runtime.Caller(0)
	basepath = filepath.Dir(currentFile)
}

func Path(rel string) string {
	if filepath.IsAbs(rel) {
		return rel
	}

	return filepath.Join(basepath, rel)
}


&lt;/code&gt;&lt;/pre&gt;</content><author><name>Mike Chirico</name><email>mchirico@gmail.com</email></author><category term="go" /><summary type="html">Some personal reminders on Go development.</summary></entry><entry><title type="html">ko with Go</title><link href="https://mchirico.github.io/golang/2022/05/16/ko.html" rel="alternate" type="text/html" title="ko with Go" /><published>2022-05-16T19:30:50+00:00</published><updated>2022-05-16T19:30:50+00:00</updated><id>https://mchirico.github.io/golang/2022/05/16/ko</id><content type="html" xml:base="https://mchirico.github.io/golang/2022/05/16/ko.html"></content><author><name>Mike Chirico</name><email>mchirico@gmail.com</email></author><category term="golang" /><summary type="html"></summary></entry><entry><title type="html">Clean Go Code</title><link href="https://mchirico.github.io/go/2021/10/30/retool.html" rel="alternate" type="text/html" title="Clean Go Code" /><published>2021-10-30T13:24:15+00:00</published><updated>2021-10-30T13:24:15+00:00</updated><id>https://mchirico.github.io/go/2021/10/30/retool</id><content type="html" xml:base="https://mchirico.github.io/go/2021/10/30/retool.html">&lt;p&gt;Good article on &lt;a href=&quot;https://github.com/Pungyeon/clean-go-article&quot;&gt;Clean Go Code&lt;/a&gt;…&lt;/p&gt;

&lt;!--  Enter text below, if you want --&gt;</content><author><name>Mike Chirico</name><email>mchirico@gmail.com</email></author><category term="Go" /><summary type="html">Good article on Clean Go Code…</summary></entry><entry><title type="html">k8s view-last-applied</title><link href="https://mchirico.github.io/k8s/2020/10/29/k8s_last_applied.html" rel="alternate" type="text/html" title="k8s view-last-applied" /><published>2020-10-29T18:13:31+00:00</published><updated>2020-10-29T18:13:31+00:00</updated><id>https://mchirico.github.io/k8s/2020/10/29/k8s_last_applied</id><content type="html" xml:base="https://mchirico.github.io/k8s/2020/10/29/k8s_last_applied.html">&lt;p&gt;Suppose you want to view the &lt;code&gt;whatever.yaml&lt;/code&gt; you applied. Is there
a way to generate this file?&lt;/p&gt;

&lt;p&gt;Note: &lt;code&gt;kubectl describe crd foos.samplecontroller.k8s.io&lt;/code&gt; would give
a lot of extra information. There’s a better way &lt;strong&gt;view-last-applied&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here’s an example, for a CRD.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;
kubectl apply view-last-applied crd foos.samplecontroller.k8s.io -o yaml

apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  annotations: {}
  labels:
    tag: foo
  name: foos.samplecontroller.k8s.io
spec:
  group: samplecontroller.k8s.io
  names:
    kind: Foo
    plural: foos
  scope: Namespaced
  version: v1alpha1


&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;deployment&quot;&gt;Deployment&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;
k get deployment

NAME             READY   UP-TO-DATE   AVAILABLE   AGE
eventer-server   1/1     1            1           7m58s

# Example..

kubectl apply view-last-applied deployment/eventer-server -o yaml

&lt;/code&gt;&lt;/pre&gt;

&lt;!--  Enter text below, if you want --&gt;</content><author><name>Mike Chirico</name><email>mchirico@gmail.com</email></author><category term="k8s" /><summary type="html">Suppose you want to view the whatever.yaml you applied. Is there a way to generate this file?</summary></entry></feed>