json: cannot unmarshal object into Go struct field

Problem

json: cannot unmarshal object into Go struct field

Code

package main

import (
	"encoding/json"
	"fmt"
)

// DTO object
type mould struct {
	Particle tiny
}

type tiny interface {
	GetName() string
}

// Implement the interface
type speck struct {
	Name string `json:"name"`
}

func (s *speck) GetName() string {
	return s.Name
}

// Constructor
func NewSpeck(name string) tiny {
	return &speck{
		Name: name,
	}
}

//
func main() {
	dirt := NewSpeck("space")

	brown := &mould{}
	brown.Particle = dirt
	brownBytes, err := json.Marshal(brown)

	if err != nil {
		panic("marshal error")
	}

	brownLike := &mould{} // unmarshal has no "idea" of how to unpack!
	err = json.Unmarshal(brownBytes, &brownLike)
	if err != nil {
		panic("unmarshal err=%+v\n", err)
		return
	}
}

Go Playground Link

The error is:

go run unmarshal_interface.go
panic: json: cannot unmarshal object into Go struct field mould.Particle of type main.tiny

The problem with code is the inability of Go runtime to get target struct for unmarshaling.

Unmarshal essentially copies the byte array to a struct type. However, in the case of the unmarshal of the type tiny, runtime could not find any destination struct. The interface in Go just has behavior, not types.

Solutions

  1. Easy! Don’t return interface in a function. 🙂
  2. Help the runtime and add some info on destination struct.
    // solution
    brownLike2 := &mould{}
    brownLike2.Particle = &speck{} // Now unmarshal "knows" how to unpack the byte array!
    
    err = json.Unmarshal(brownBytes, &brownLike2)
    fmt.Printf("brownLike2=%#v err=%+v\n", brownLike2.Particle.GetName(), err)
    

Refernces

Written with StackEdit.

Quick Read on UTF-8 in Golang

Raw Strings

we create a “raw string”, enclosed by back quotes, so it can contain only literal text.
Regular strings, enclosed by double quotes, can contain escape sequences as we showed above.

package main

import (
	"fmt"
)

func main() {

	fmt.Println(`go\\n`)
	fmt.Println("escapedGo\\n")
}

Output

go\\n
escapedGo\n
  • Raw string is always UTF-8 because it is part of the Go source code which is always UTF-8.
  • strings can contain arbitrary bytes, but when constructed from string literals, those bytes are (almost always) UTF-8.

Rune

  • 32 bit integer
  • Used to represent a UTF-8 code point of upto 4 bytes
  • Example
    • The Unicode code point U+0061 is the lower case Latin letter ‘A’: a.
    • There are at least two ways to write letter à:
      • Code point of à is U+00E0
      • Code point of grave accent (U+0300) + U+00E0

So there are different byte sequences for the same character!

How Golang handle literals?

  • A literal is a valid UTF-8 sequence.
  • It is always true for a literal
    `aLiteral`
    

Strings are built from bytes so indexing them yields bytes, not characters. A string might not even hold characters.

References

Benefits of Monorepo

#build #monorepo

Why Mono-repo

  • Using a monorepo where HEAD always points to a consistent and valid version removes the problem of tracking multiple repo versions entirely
  • Static analysis can run across project boundaries without any extra work.
  • Many other things, like cross-project integration testing and code search are also greatly simplified.
  • You just refactor the API and all of its callers in one commit. That’s not always trivial, but it’s much easier than it would be with lots of small repos.
  • Making cross-project changes is easier, tracking them is easier.

Example: Google Reader

Google Reader was discontinued!

Why It was Hard to Open-Source Google Reader?

Because of all the available libraries, it maybe took a few hours to write a simple, scalable, fault-tolerant RSS fetcher. And look, we created another library someone else inside of Google could integrate into their project. Imagine what happens when you have thousands of engineers building re-usable modules (on top of other modules) over the course of a decade.

Open source Lags Due to Multi-repo Eco-system

This sort of Lego-like development process does not happen as cleanly in the open source world.

  • Some tools (e.g. Maven) do manage to make this a lot easier, at least under certain controlled conditions.
  • Hosted source control (e.g. Github) has also lowered the effort required to do open source development.

Empirically, though, what it truly enabled (speculating) was a large number of small projects rather than an increase in individual project complexity.

Reference

Written with StackEdit.

HTTP Request Body for Form Values

HTTP Request Header

HTTP clients and servers largely depend on the “Content-Type” header to determine how to parse the request/response body. Common values for the “Content-Type” header are

  • application/json
  • application/atom+xml
  • application/pdf
  • application/octet-stream
  • application/x-www-form-urlencoded

and request/response body should be processed as JSON, XML, PDF, Raw Stream, or Form Data respectively.

How is Form Data Sent?

99.99% of forms in your web applications will be url-encoded and sent in the request body instead of the request URL for obvious reasons.

Parse Form Data with ParseForm()

func (r *Request) ParseForm() error
For all requests, ParseForm parses the raw query from the URL and updates r.Form.

For POST, PUT, and PATCH requests, it also reads the request body, parses it as
a form, and puts the results into both r.PostForm and r.Form. Request body 
parameters take precedence over URL query string values in r.Form.

If the request Body's size has not already been limited by MaxBytesReader,
the size is capped at 10MB.

For other HTTP methods, or when the Content-Type is not 
application/x-www-form-urlencoded, the request Body is not read, and r.PostForm
is initialized to a non-nil, empty value.

URL query parameters are also read in the r.Form map object.

References

Written with StackEdit.

How to Check nil Interface in Golang?

Never check an interface for nil.

Try the following code:

type user interface{}
type staff struct{}

func compareNil() {
    var generic user

	generic = (*staff)(nil)

	fmt.Printf("value=%v type=%T (generic==nil)=%v\n", generic, generic, generic == nil)

	generic = (nil)

	fmt.Printf("value=%v type=%T (generic==nil)=%v\n", generic, generic, generic == nil)
}

go playground: https://play.golang.org/p/7J9DeIjgNia

Output
value=<nil> type=*main.staff (generic==nil)=false
value=<nil> type=<nil> (generic==nil)=true
Why interface check for nil is special

An interface is a tuple of [Value, Type]. The nil interface is a tuple [nil, nil]. However, the above code is an interface containing [nil, *main.staff] which is not nil.

We can check for nil as follows:

func isNil(i interface{}) bool {                        
    return i == nil || reflect.ValueOf(i).IsNil() 
}

Here i==nil means i has [nil, nil] or has a nil value in [nil, *main.staff].

But if the interface points to a type that has no Nil value:

s := "hello"
generic = s
fmt.Printf("value=%v type=%T type=%v\n", generic, generic, reflect.ValueOf(generic).IsNil())

The code panics:

panic: reflect: call of reflect.Value.IsNil on string Value

goroutine 1 [running]:
reflect.Value.IsNil(...)
        /Users/xxx/.goenv/versions/1.14.0/src/reflect/value.go:1063
main.compareNil()
        /Users/xxx/go/1.14.0/src/mygo/interfaces/interfaces.go:48 +0x3b1
main.main()
        /Users/xxx/go/1.14.0/src/mygo/interfaces/interfaces.go:29 +0x142
exit status 2

Conclusion

The safest way to compare nil interfaces is switch on various types the interface can assume. Never check as myinterface == nil.

References

Why HTTP Status in Response is always StatusOK?

Why the following code works as expected but the next one does not?

Response 1

resp.WriteHeader(http.StatusBadRequest)
_, _ = resp.Write([]byte(`status code is 400`))

But if we change the order and write the body first and header later:

Response 2

_, _ = resp.Write([]byte(`status code is not 400!!`))
resp.WriteHeader(http.StatusBadRequest)

The header is set to http.StatusOK in Response 2.

Why does the order matter?

from .goenv/versions/1.14.0/src/net/http/server.go

    // If WriteHeader has not yet been called, Write calls
	// WriteHeader(http.StatusOK) before writing the data. 
    // Changing the header map after a call to WriteHeader (or
	// Write) has no effect unless the modified headers are
	// trailers.

So be careful and always write the status first, body next.

References

Golang: Careful with Named Return Parameters in Function

package main

import (
	"fmt"
)

func riskyParams() (num int, flag bool) {
    if num == 0 {  // Named parameters have default values in the scope
        flag = true
    }
	return // Beware of such return. You might return something unintended  
}

func main() {
	num, flag := riskyParams()
	fmt.Printf("num=%d flag=%v\n", num, flag)
}

The example highlights unintended side-effects of named return parameters.

Written with StackEdit.

The Best Git Commands for Dev

The most common part is:

The basic cycle

git pull master to get up to date

git checkout -b myname-feature to get a branch of your own

git add <files> that you changed/created
git add . to add everything in the current directory
git add -u to add all existing files in the repo

git commit
git commit -m "multiline commits" -m "without text editors" -m "wow!"

git push -u origin myname-feature the first time, git push after that

git branch -D myname-feature when it gets merged into master and you don’t need it cluttering your autocomplete anymore

Also read on

  • cherry-pick
  • reset commit
  • reset a file

The complete info is available at:
https://stu2b50.dev/posts/things-you-wante9665

Redis Expire Key: How TTL behaves?

  • An operation that modifies a key’s value resets the TTL.
  • An operation that alters the key’s value leaves TTL untouched.

Create a list with TTL = 120

redis> rpush "mylist" "first"  
(integer) 1  
  
redis> rpush "mylist" "second"  
(integer) 2  
  
redis> expire "mylist" 120  
(integer) 1  

Add new elements to the list and verify TTL

redis> TTL mylist  
(integer) 99  

redis> rpush "mylist" "second"  
(integer) 3  
  
redis> TTL mylist  
(integer) 79  

However, a call to EXPIRE will refresh the TTL.

References

Liveness vs Readiness Health Checks in Application

The liveness check finds if the application is alive or not. The application defines the logic and the liveness check verifies the expected output.
A webserver liveness check could include an HTTP handler that returns a fixed response or checks application dependencies.

Sample Liveness check

  • send a pong response in the handler
  • combine health check of all dependencies and return true/false

The Readiness check is to know if an application can accept traffic after initialization. A use case is a wait to serve traffic until all dependencies are ready. Essentially both checks have similar config options.

Sample Readiness Check

  • combine health check of all dependencies and return true/false
  • A init wait of 5 secs

References

Written with StackEdit.

%d bloggers like this: