  Go is a production-level statically typed programming language whose design
features explicit message-passing primitives and lightweight threads, enabling
(and encouraging) programmers to develop concurrent systems where components
interact through communication more so than by lock-based shared memory
concurrency. Go can only detect global deadlocks at runtime, but provides no
compile-time protection against all too common communication mismatches or
partial deadlocks. This work develops a static verification framework for
liveness and safety in Go programs, able to detect communication errors and
partial deadlocks in a general class of realistic concurrent programs,
including those with dynamic channel creation, unbounded thread creation and
recursion. Our approach infers from a Go program a faithful representation of
its communication patterns as a behavioural type. By checking a syntactic
restriction on channel usage, dubbed fencing, we ensure that programs are made
up of finitely many different communication patterns that may be repeated
infinitely many times. This restriction allows us to implement procedures to
check for liveness and safety in types which in turn approximates liveness and
safety in Go programs. We have implemented a type inference and liveness and
safety checks in a tool-chain and tested it against publicly available Go
programs.
  Note: This is a revised extended version of a paper that appeared in POPL
2017, see page 13 for details.
