Would you care to elaborate? I can’t think of any case where returning a pointer to a slice is a good idea. It would let you distinguish between p == nil vs. *p == nil, but I would be interested in seeing the code that uses the result. I imaging there would be a better way to do that (e.g. return a pointer to a struct with a single slice field, maybe?).
However, I do agree with you that you should have a reason to use a pointer and if you don’t know if you do or not, then you do not need a pointer.
Slices hold references to an underlying array, and if you assign one slice to another, both refer to the same array. If a function takes a slice argument, changes it makes to the elements of the slice will be visible to the caller, analogous to passing a pointer to the underlying array.
If you pass or return a single Category, then there will be a copy of all the fields. If you put a Category in a slice, then there will be a copy of all the fields at that time. If you pass or return a slice of Categories, then there will be no additional copies of Category data. If you pass or return pointer to a Category, then there are no copies (other than the 8 bytes for the pointer), but the Category referred to by the pointer may be modified from two bits of code and that may cause bugs. Putting a pointer in a slice will also not copy the Category, and you can get similar sharing. Returning a slice of Categories vs a slice of Category pointers has no difference in the quantity of data copied. Returning a slice allows possible sharing of the Categories or pointers in the slice because the data backing the slice is visible to all copies of the slice. There’s little point to returning a pointer to a slice other than copying a pointer means copying 8 bytes and copying a slice means copying 24 bytes. Perhaps one could use unsafe access to modify a slice’s internal data, but that is highly irregular. (Byte counts may be different in different environments, but the point is that copying a slice is only slightly more expensive than copying a pointer.)
I will add that returning copies of data is pretty efficient for the most part. Unless Category has a giant chunk of binary data (like a video or something), I doubt you will run into a problem in the real world. So, this is probably premature optimization. Your bottleneck will almost certainly be in another layer (such as data access, doing a bunch of joins to return the large chunk of category data in the first place).