Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doc: filename conventions #36060

Open
carnott-snap opened this issue Dec 9, 2019 · 20 comments
Open

doc: filename conventions #36060

carnott-snap opened this issue Dec 9, 2019 · 20 comments
Labels
Documentation NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made.
Milestone

Comments

@carnott-snap
Copy link

If I have simply missed where this is documented, please let me know where I should have looked, and close this out.

Many places describe how custom filename suffixes interact with the toolchain: _test, _linux, _arm. However I cannot find anywhere that says you should use snake case for multi-word file names, as is suggested by the standard library: e.g. time/zoneinfo_read.go/os/removeall_at.go not time/zoneinfoRead.go/os/removeallAt.go or time/zoneinfo-read.go/os/removeall-at.go.

This may seem self evident to experienced users, but I have seen many people get confused by the fact that variables use CamelCase := "", while files use snake_case.go.

@toothrot
Copy link
Contributor

toothrot commented Dec 9, 2019

I am not certain where this convention is documented, but I feel like @ianlancetaylor or @bradfitz might have some guidance.

@dmitshur
Copy link
Contributor

dmitshur commented Dec 9, 2019

To my knowledge, there isn't a documented convention for .go file names (other than meaningful things like _test.go, leading . or _, trailing _goos_goarch, etc.) anywhere. I've checked https://golang.org/doc/effective_go.html and https://golang.org/s/style.

The Go project itself tends to prefer short names like io.go, pipe.go, etc. In the rare cases two words are needed, they are joined without an underscore, like cputicks.go or debugcall.go. For more complicated packages with many files, underscores are sometimes used when additional separation is needed.

@carnott-snap
Copy link
Author

carnott-snap commented Dec 10, 2019

That is useful to note. It led me down a bit of a rabbit hole, and it looks like even the standard library is not consistent (though lowercasealloneword seems to be in the plurality). Should we make a standard?

file.extension.go

out:
- cmd/internal/obj/arm/a.out.go
- cmd/internal/obj/arm64/a.out.go
- cmd/internal/obj/mips/a.out.go
- cmd/internal/obj/ppc64/a.out.go
- cmd/internal/obj/s390x/a.out.go
- cmd/internal/obj/wasm/a.out.go
- cmd/internal/obj/x86/a.out.go

snake_case.go

marshaling:
- encoding/json/example_marshaling_test.go
- encoding/json/example_text_marshaling_test.go
- encoding/xml/example_marshaling_test.go
- encoding/xml/example_text_marshaling_test.go
mmap:
- cmd/compile/internal/gc/mapfile_mmap.go
- cmd/internal/bio/buf_mmap.go
- cmd/link/internal/ld/outbuf_mmap.go
- runtime/cgo_mmap.go
- runtime/export_mmap_test.go
- runtime/runtime_mmap_test.go
string:
- cmd/compile/internal/gc/class_string.go
- cmd/compile/internal/gc/op_string.go
- cmd/compile/internal/syntax/operator_string.go
- cmd/compile/internal/syntax/token_string.go
- cmd/compile/internal/types/etype_string.go
- cmd/internal/obj/abi_string.go
- cmd/internal/obj/addrtype_string.go
- cmd/internal/objabi/reloctype_string.go
- cmd/internal/objabi/symkind_string.go
- cmd/link/internal/sym/symkind_string.go
- debug/dwarf/attr_string.go
- debug/dwarf/class_string.go
- debug/dwarf/tag_string.go
- debug/macho/reloctype_string.go
- html/template/attr_string.go
- html/template/delim_string.go
- html/template/element_string.go
- html/template/jsctx_string.go
- html/template/state_string.go
- html/template/urlpart_string.go
- math/big/accuracy_string.go
- math/big/roundingmode_string.go
- regexp/syntax/op_string.go
sysnum:
- internal/syscall/unix/at_sysnum_darwin.go
- internal/syscall/unix/at_sysnum_dragonfly.go
- internal/syscall/unix/at_sysnum_fstatat64_linux.go
- internal/syscall/unix/at_sysnum_fstatat_linux.go
- internal/syscall/unix/at_sysnum_linux.go
- internal/syscall/unix/at_sysnum_netbsd.go
- internal/syscall/unix/at_sysnum_newfstatat_linux.go
- internal/syscall/unix/at_sysnum_openbsd.go

lowercase.go

gccgoinstallation:
- go/internal/gccgoimporter/gccgoinstallation_test.go
loopreschedchecks:
- cmd/compile/internal/ssa/loopreschedchecks.go
mkfastlog2table:
- runtime/mkfastlog2table.go
mksizeclasses:
- runtime/mksizeclasses.go
obscuretestdata:
- internal/obscuretestdata/obscuretestdata.go
reproduciblebuilds:
- cmd/compile/internal/gc/reproduciblebuilds_test.go

CamelCase.go

386Ops:
- cmd/compile/internal/ssa/gen/386Ops.go
"387":
- cmd/compile/internal/x86/387.go
AMD64Ops:
- cmd/compile/internal/ssa/gen/AMD64Ops.go
ARM64Ops:
- cmd/compile/internal/ssa/gen/ARM64Ops.go
ARMOps:
- cmd/compile/internal/ssa/gen/ARMOps.go
MIPS64Ops:
- cmd/compile/internal/ssa/gen/MIPS64Ops.go
MIPSOps:
- cmd/compile/internal/ssa/gen/MIPSOps.go
PPC64Ops:
- cmd/compile/internal/ssa/gen/PPC64Ops.go
S390XOps:
- cmd/compile/internal/ssa/gen/S390XOps.go
WasmOps:
- cmd/compile/internal/ssa/gen/WasmOps.go
arithBoundary:
- cmd/compile/internal/gc/testdata/arithBoundary_test.go
arithBoundaryGen:
- cmd/compile/internal/gc/testdata/gen/arithBoundaryGen.go
arithConst:
- cmd/compile/internal/gc/testdata/arithConst_test.go
arithConstGen:
- cmd/compile/internal/gc/testdata/gen/arithConstGen.go
deferNoReturn:
- cmd/compile/internal/gc/testdata/deferNoReturn_test.go

@ianlancetaylor
Copy link
Contributor

Although the compiler made a different choice, for the standard library we've historically preferred all lowercase just to avoid confusion on case-insensitive systems. I don't know that this is written down anywhere. I don't know that we have any particular guidance for file names in packages outside the standard library.

@dmitshur dmitshur added the NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. label Dec 14, 2019
@dmitshur
Copy link
Contributor

dmitshur commented Dec 14, 2019

I don't know that we have any particular guidance for file names in packages outside the standard library.

To make progress on this issue, we need to decide if we should change that and attempt to offer guidance by adding an entry to https://golang.org/doc/effective_go.html or https://golang.org/s/style, or if we should not.

At this time, I'm inclined to believe we should not.

People who care about this can look at the .go file naming strategies used by the Go standard library and mimic it. Those who don't care can choose a naming strategy that they prefer.

There are additional resources where people write down their opinions on Go style, such as those listed at https://medium.com/@dgryski/idiomatic-go-resources-966535376dba. Perhaps an entry in one of those lists would be more viable.

@carnott-snap
Copy link
Author

I opened this issue because I have colleagues that asked, what filename conventions should I use with go?

I can understand that trying to stabilise this now may be problematic, noisy, or too late. But the lack of consensus will cause some amount of confusion and cognitive overhead. Because the community (seems to) understand the benefits of standardisation, see gofmt, even a soft recommendation in a blog post would go a long way.

@peterbourgon
Copy link

peterbourgon commented Jan 30, 2020

There is a de facto standard for Go source file names: all lowercase with underscore separation when necessary, i.e. snake case. (The exceptions are exceptions.) I'd appreciate having it as a documented standard, too, to answer questions like @carnott-snap notes, especially among junior Gophers. In my opinion it needn't be so formal as entering Effective Go, a short new section on CodeReviewComments is more than sufficient.

File names

Go source file names should be lowercase_with_underscores.go and not camelCase.go or TitleCase.go. This makes them consistent with other language conventions, like _test.go for test files, or _windows.go for build constraints. It also prevents ambiguities on case-insensitive file systems.

@tv42
Copy link

tv42 commented Sep 16, 2021

Related, documenting what's allowed as opposed to recommended might be useful too.

// If first letter of input file is ASCII, it must be alphanumeric.
// This avoids files turning into flags when invoking commands,
// and other problems we haven't thought of yet.
// Also, _cgo_ files must be generated by us, not supplied.
// They are allowed to have //go:cgo_ldflag directives.
// The directory scan ignores files beginning with _,
// so we shouldn't see any _cgo_ files anyway, but just be safe.
for _, file := range inputs {
if !SafeArg(file) || strings.HasPrefix(file, "_cgo_") {
setError(fmt.Errorf("invalid input file name %q", file))
return
}
}

// SafeArg reports whether arg is a "safe" command-line argument,
// meaning that when it appears in a command-line, it probably
// doesn't have some special meaning other than its own name.
// Obviously args beginning with - are not safe (they look like flags).
// Less obviously, args beginning with @ are not safe (they look like
// GNU binutils flagfile specifiers, sometimes called "response files").
// To be conservative, we reject almost any arg beginning with non-alphanumeric ASCII.
// We accept leading . _ and / as likely in file system paths.
// There is a copy of this function in cmd/compile/internal/gc/noder.go.
func SafeArg(name string) bool {
if name == "" {
return false
}
c := name[0]
return '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || c == '.' || c == '_' || c == '/' || c >= utf8.RuneSelf
}

@matteoolivi
Copy link

Any progress/plan to document this somewhere?

@urandom2
Copy link
Contributor

@peterbourgon, can we just add your text to the wiki? I did not see strong consensus, but this is an easy one and we should probably just fix it.

@dfang
Copy link

dfang commented Mar 22, 2022

I agree with all lowercase with underscore separation when necessary, apparently greet_controller.go or greet_handler.go is more readable than greetcontroller.go and greet_handler.go.

you can gh repo clone golang/go or gh repo clone kubernetes/kubernetes source code to your local and run find . -iname "*_*.go" | egrep -v 'test|arm|darwin|openbsd|unix|windows|plan9', most file names are lowercase with underscore separation style.

this is the convention, just undocumented yet.

@tv42
Copy link

tv42 commented Apr 19, 2022

The downside of blah_thing.go is that thing might get added as a new recognized architecture or operating system. It's just an unpleasant namespacing clash.

Imagine writing a game with npc_human.go, npc_monster.go, npc_android.go, and then Android gets released.

Imagine having embed_svg.go, embed_html.go, and embed_js.go, and then the platform js/wasm gets added.

Neither blahthing.go nor blahThing.go are vulnerable to that. Generally all lowercase is less likely to get damaged by OS X users. I'm almost tempted to use - where needed just to avoid that build tag collision.

hahuang65 added a commit to hahuang65/gophercises that referenced this issue May 24, 2022
Go doesn't have a standardized way of naming files:

golang/go#36060

But I'm going with snakecase, since `go test` finds files using the
`*_test.go` convention.
hahuang65 added a commit to hahuang65/gophercises that referenced this issue May 24, 2022
Go doesn't have a standardized way of naming files:

golang/go#36060

But I'm going with snakecase, since `go test` finds files using the
`*_test.go` convention.
hahuang65 added a commit to hahuang65/gophercises that referenced this issue May 24, 2022
Go doesn't have a standardized way of naming files:

golang/go#36060

But I'm going with snakecase, since `go test` finds files using the
`*_test.go` convention.
@bahag-salarzehis
Copy link

no standards defined yet?

@SpicyLemon
Copy link

In addition to a recommended naming convention, I'd also like to see a list of all specially handled filenames and directories. E.g. *_test.go only compiled with go test, and nothing in internal directories exported outside the module. I'm not sure what else there might be. Is testutil special? I'm sure there's others that are special too.

@takanuva15
Copy link

@peterbourgon, can we just add your text to the wiki? I did not see strong consensus, but this is an easy one and we should probably just fix it.

Peter's comment has more likes than the original issue lol. I was looking for the same thing on Golang file naming conventions and was surprised to see that effective go doesn't discuss it even though it touches on naming for pretty much everything else.

@tv42 makes a valid point, so we could add it as a disclaimer under Peter's text so we at least have something listed in Effective Go for this (as opposed to telling people to read other sites for a convention 🙃 ).

@urandom2 Since you've already merged a PR here before, how easy is it to just raise a PR in the effective go docs and add this section? Do you already know which file to update to add a new subsection to the docs?

@gophun
Copy link

gophun commented Dec 11, 2023

how easy is it to just raise a PR in the effective go docs and add this section?

A better place would be https://go.dev/doc/modules/layout, since Effective Go is frozen, as mentioned at the end of its 'Introduction' section.

inesusvet added a commit to facebookincubator/TTPForge that referenced this issue Feb 29, 2024
Summary:
Rename file, actualize success message.

Reference to open issue about file naming in golang projects
golang/go#36060

Differential Revision: D54360635
inesusvet added a commit to facebookincubator/TTPForge that referenced this issue Mar 1, 2024
Summary:
Rename file, actualize success message.

Reference to open issue about file naming in golang projects
golang/go#36060

Reviewed By: l50

Differential Revision: D54360635
facebook-github-bot pushed a commit to facebookincubator/TTPForge that referenced this issue Mar 1, 2024
Summary:
Rename file, actualize success message.

Reference to open issue about file naming in golang projects
golang/go#36060

Reviewed By: l50

Differential Revision: D54360635

fbshipit-source-id: 1631f876273e89baa53755254fdc57d7d662dd4f
@style95
Copy link

style95 commented Mar 27, 2024

So is snake case the standard according to @peterbourgon's comments?

@tempcke
Copy link

tempcke commented Jun 20, 2024

I rather like @tv42 's comment contemplating the use of -

This way there is no potential conflict with the special handling of some _suffix 's

The only downside is that it isn't ever used in the standard library filenames near as I can tell. So it feels like breaking convention. Is there any good reason aside from that though to not use - 's?

@zealsprince
Copy link

zealsprince commented Jul 15, 2024

I've also been gravitating heavily toward kebab-case over the last few years since I find sometimes I want to visually grep files in tree views.

As an example I'm working with an internal models package which stores model definitions as well as helper methods with shared functionality between these models. As such, I name each model definition model-a.go and model-b.go and so on to avoid visual conflicts with other files that do not pertain to a single model and rather shared concepts and generics.

That way, I can easily find a shared.go. I understand that an argument would be to decompose these into further packages but this adds needless complexity. At the same time I find bunching these into a single models.go feels bloated and leads to long and hard to navigate code that is not easily separable in terms of concept.

I think this plays into @tv42's mention that it won't break _suffix conventions in the future while overall being a more visual pleasing way of quickly navigating a lot of files that do not make sense to be stored in their own packages.

@tarasyyyk
Copy link

source_file--linux.go

text_marshaling--test.go

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Documentation NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made.
Projects
None yet
Development

No branches or pull requests