How to Parse an ARN in Go
Part of the AWS Toolkitparts := strings.SplitN(arn, ":", 6)n=6 means six pieces, not six splits — check len(parts) before indexing, since a short slice panics instead of returning a zero value
Explanation
An ARN has six colon-separated fields, but the resource field isn't guaranteed to be colon-free — a Lambda function version ARN packs a third piece into it:
arn:aws:lambda:us-east-1:123456789012:function:my-function:1Plain strings.Split(arn, ":") gives you eight elements here, not six, so indexing by position grabs the wrong piece. Go's fix is strings.SplitN, which takes a count argument:
parts := strings.SplitN(arn, ":", 6)Per the standard library docs, "the last substring will be the unsplit remainder" — with n = 6, that's parts[5], and it absorbs every colon left over instead of stopping at the first one. Applied to the Lambda ARN above, parts[5] comes back as the full "function:my-function:1", untouched.
Watch the off-by-one here against the equivalent in other languages: SplitN's third argument is the number of pieces you want back (6), not the number of splits, which is what Python's maxsplit counts (5, for the same result) — see How to Parse an ARN in Python for that version.
Go has one more sharp edge the other languages don't: indexing a slice past its length doesn't return undefined or None, it panics. If the string you pass in isn't actually a well-formed ARN — a truncated string, a typo, a value from an untrusted source — SplitN can return fewer than six elements, and reading parts[5] without checking len(parts) first crashes the program instead of producing a wrong-but-safe result. Always check the length before indexing.
The same colons-in-the-resource trap applies to a hand-written regex, too: a pattern using [^:]+ for every group excludes colons entirely, so it won't match the Lambda ARN at all — use a greedy (.+) for the final group instead.
Java's String.split uses the same limit-as-piece-count convention — see How to Parse an ARN in Java, which also has its own sharp edge: the separator is compiled as a regex, not matched literally.
For the full field-by-field breakdown of a specific ARN, see ARN Parser. For what each field means, see What Is an ARN?
Valid examples
strings.SplitN("arn:aws:iam::123456789012:user/john", ":", 6) → ["arn" "aws" "iam" "" "123456789012" "user/john"]Exactly six pieces — SplitN doesn't change anything when there's nothing extra to protect.
strings.SplitN("arn:aws:lambda:us-east-1:123456789012:function:my-function:1", ":", 6) → [..., "function:my-function:1"]The sixth element absorbs both remaining colons instead of being cut off at the first one.
strings.SplitN("arn:aws:s3:::amzn-s3-demo-bucket/Development/*", ":", 6) → ["arn" "aws" "s3" "" "" "amzn-s3-demo-bucket/Development/*"]region and account ID both come back as empty strings for an S3 bucket ARN — present, just empty.
Invalid examples
strings.Split(arn, ":")[5] // "function", not "function:my-function:1"Splitting with no count and indexing by position — the Lambda ARN above has 8 parts, not 6, so [5] grabs the wrong piece.
parts := strings.SplitN("arn:aws:s3", ":", 6); parts[5]A truncated or malformed ARN produces fewer than 6 elements — indexing [5] without checking len(parts) first panics: index out of range.
regexp.MustCompile(`^arn:([^:]+):([^:]+):([^:]*):([^:]*):([^:]+)$`)Every group uses [^:]+ — fails to match the Lambda ARN, since its resource part contains colons the pattern explicitly excludes.