how can I add a 2D label to a 3D GameObject?

Hello, I have a number of GameObjects in an array, in varying number, and I want to add a UI label at some position over them. I want to do this by script, because my objects may change. I have tried the following, with a Canvas and attaching the script to the main camera, and I see the sphere, but no label is shown.
Am I missing something obvious?

Thanks.

using UnityEngine;
using UnityEngine.UI;

public class Bug : MonoBehaviour
{
  Canvas canv;
  GameObject[] obj=new GameObject[100];
  Text objlabel;

  void Start()
    {
      canv = GameObject.Find("Canvas").GetComponent<Canvas>();
      Camera.main.transform.position = new Vector3(5, 5, -10);
      obj[0] = GameObject.CreatePrimitive(PrimitiveType.Sphere);
      obj[0].transform.position = new Vector3(-7.5f,6.0f,1.4f);
      obj[0].SetActive(false); // hide the sphere
      
      GameObject golab=new GameObject("Lab1");
      objlabel=golab.AddComponent<Text>();
      objlabel.text="XXXXX";
      objlabel.transform.SetParent(canv.transform);

      Vector3 namePos=Camera.main.WorldToScreenPoint(obj[0].transform.position);
      objlabel.transform.position=namePos;
    }

  void Update()
    {}
}

Here’s some code that I use for that.

        // Add namePlate here after instaniation.
        namePlate = new GameObject("NamePlate");
        namePlate.AddComponent<TextMesh>();            // To display name.
        // Adjust position and settings.
        TextMesh textMesh = namePlate.GetComponent<TextMesh>();
        if (textMesh != null)
        {
            Debug.Log("Adding Nameplate");
            textMesh.transform.position = player.transform.position + new Vector3(0, 1.3f, 0);  // elevate y
            textMesh.transform.rotation = player.transform.rotation * new Quaternion(0, 180.0f, 0, 0);  // turn it around
            textMesh.characterSize = 0.2f;
            textMesh.fontSize = 10;
            textMesh.alignment = TextAlignment.Center;
            textMesh.anchor = TextAnchor.MiddleCenter;
            textMesh.color = Color.white;
            textMesh.text = id;     // Set the name text to the network id string.
        }
        // Now set the new Player object as its parent.
        namePlate.transform.parent = player.transform;

Thanks, here is my improved version, without a Canvas:

public class Bug2 : MonoBehaviour
{
  GameObject[] obj=new GameObject[100];
  TextMesh objlabel;

  void Start()
    {
      Camera.main.transform.position = new Vector3(5, 5, -10);
      obj[0] = GameObject.CreatePrimitive(PrimitiveType.Sphere);
      obj[0].transform.position = new Vector3(-7.5f,6.0f,1.4f);
      obj[0].SetActive(true); // if false, hide the sphere (and the label)
      
      GameObject golab=new GameObject("Lab1");
      objlabel=golab.AddComponent<TextMesh>();
      objlabel.text="Sphere";
      objlabel.alignment = TextAlignment.Center;
      objlabel.anchor = TextAnchor.MiddleCenter;
      objlabel.color = Color.red;

      objlabel.transform.parent=obj[0].transform; 
      objlabel.transform.position=obj[0].transform.position+new Vector3(0,2,0);
    }

  void Update()
    {}
}